library(ggpubr)
Registered S3 method overwritten by 'data.table':
method from
print.data.table
Registered S3 methods overwritten by 'car':
method from
influence.merMod lme4
cooks.distance.influence.merMod lme4
dfbeta.influence.merMod lme4
dfbetas.influence.merMod lme4
response <- try(system('~/google-cloud-sdk/bin/gcloud projects list --quiet', intern = T))
projectid <- strsplit(response[2], " ")[[1]][1]
options(na.action = "na.fail")
source("./dredge_functions.R")
dredge_and_subset <- function(data) {
model <- lm(
response ~ foraging_niche + trophic_niche + is_nocturnal + pc1 + pc2 + pc3 + pc4 + total_species,
data=data
)
dredge_result <- dredge(model)
summary(model.avg(dredge_result, subset = delta < 10))
}
load_niche_data <- function() {
filename <- 'species_analysis_cache.csv'
if (!file.exists(filename)) {
sql <- "
SELECT
niche_name,
foraging_niche,
trophic_niche,
is_noctural,
total_species,
merlin_10_perc_ratio,
merlin_20_perc_ratio,
merlin_ever_perc_ratio,
birdlife_10_perc_ratio,
birdlife_20_perc_ratio,
birdlife_ever_perc_ratio,
either_10_perc_ratio,
either_20_perc_ratio,
either_ever_perc_ratio,
both_10_perc_ratio,
both_20_perc_ratio,
both_ever_perc_ratio,
body_morphspace.pc1.mean AS pc1,
body_morphspace.pc2.mean AS pc2,
body_morphspace.pc3.mean AS pc3,
body_morphspace.pc4.mean AS pc4
FROM `endless-matter-297214.model2.niche_analysis_model` LIMIT 1000
"
tb <- bq_project_query(projectid, sql)
data <- bq_table_download(tb)
write_csv(data, filename)
}
data <- read_csv(filename)
data[is.na(data$foraging_niche),]$foraging_niche <- 'Omnivore'
data$foraging_niche = as.factor(data$foraging_niche)
data$trophic_niche = as.factor(data$trophic_niche)
data$is_nocturnal = as.factor(data$is_noctural)
data
}
data_for_response <- function(column_name_for_response) {
data <- load_niche_data()
names(data)[names(data) == column_name_for_response] <- "response"
data[,c("niche_name", "response", "foraging_niche", "trophic_niche", "is_nocturnal", "pc1", "pc2", "pc3", "pc4", "total_species")]
}
| 0.25 Percentile - 10% of species |
merlin_10_data <- data_for_response('merlin_10_perc_ratio')
── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
.default = col_double(),
niche_name = col_character(),
foraging_niche = col_character(),
trophic_niche = col_character(),
is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
merlin_10_data
merlin_10_result <- dredge_and_subset(merlin_10_data)
Fixed term is "(Intercept)"
merlin_10_summ <- model_summary('merlin_10', 'species', merlin_10_result)
merlin_10_summ
birdlife_10_data <- data_for_response('birdlife_10_perc_ratio')
── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
.default = col_double(),
niche_name = col_character(),
foraging_niche = col_character(),
trophic_niche = col_character(),
is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
birdlife_10_result <- dredge_and_subset(birdlife_10_data)
Fixed term is "(Intercept)"
birdlife_10_summ <- model_summary('birdlife_10', 'species', birdlife_10_result)
birdlife_10_summ
both_10_data <- data_for_response('both_10_perc_ratio')
── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
.default = col_double(),
niche_name = col_character(),
foraging_niche = col_character(),
trophic_niche = col_character(),
is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
both_10_result <- dredge_and_subset(both_10_data)
Fixed term is "(Intercept)"
both_10_summ <- model_summary('both_10', 'species', both_10_result)
both_10_summ
either_10_data <- data_for_response('either_10_perc_ratio')
── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
.default = col_double(),
niche_name = col_character(),
foraging_niche = col_character(),
trophic_niche = col_character(),
is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
either_10_result <- dredge_and_subset(either_10_data)
Fixed term is "(Intercept)"
either_10_summ <- model_summary('either_10', 'species', either_10_result)
either_10_summ
| Full result for 10% of species |
all_species_results <- full_join(full_join(merlin_10_summ, birdlife_10_summ), full_join(both_10_summ, either_10_summ))
Joining, by = c("explanatory", "model")
Joining, by = c("explanatory", "model")
Joining, by = c("explanatory", "model")
write_csv(all_species_results, "species_analysis_result_10_perc.csv")
| 0.75 Percentile - 20% of species |
merlin_20_data <- data_for_response('merlin_20_perc_ratio')
── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
.default = col_double(),
niche_name = col_character(),
foraging_niche = col_character(),
trophic_niche = col_character(),
is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
merlin_20_result <- dredge_and_subset(merlin_20_data)
Fixed term is "(Intercept)"
merlin_20_summ <- model_summary('merlin_20', 'species', merlin_20_result)
merlin_20_summ
birdlife_20_data <- data_for_response('birdlife_20_perc_ratio')
── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
.default = col_double(),
niche_name = col_character(),
foraging_niche = col_character(),
trophic_niche = col_character(),
is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
birdlife_20_result <- dredge_and_subset(birdlife_20_data)
Fixed term is "(Intercept)"
birdlife_20_summ <- model_summary('birdlife_20', 'species', birdlife_20_result)
birdlife_20_summ
both_20_data <- data_for_response('both_20_perc_ratio')
── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
.default = col_double(),
niche_name = col_character(),
foraging_niche = col_character(),
trophic_niche = col_character(),
is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
both_20_result <- dredge_and_subset(both_20_data)
Fixed term is "(Intercept)"
both_20_summ <- model_summary('both_20', 'species', both_20_result)
both_20_summ
either_20_data <- data_for_response('either_20_perc_ratio')
── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
.default = col_double(),
niche_name = col_character(),
foraging_niche = col_character(),
trophic_niche = col_character(),
is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
either_20_result <- dredge_and_subset(either_20_data)
Fixed term is "(Intercept)"
either_20_summ <- model_summary('either_20', 'species', either_20_result)
either_20_summ
| Full result for 10% of species |
all_species_results <- full_join(full_join(merlin_20_summ, birdlife_20_summ), full_join(both_20_summ, either_20_summ))
Joining, by = c("explanatory", "model")
Joining, by = c("explanatory", "model")
Joining, by = c("explanatory", "model")
write_csv(all_species_results, "species_analysis_result_20_perc.csv")
| Comparing the 2 percentiles |
ggplot(merlin_10_data, aes(x = response)) + geom_bar(width = 0.1)
Warning: position_stack requires non-overlapping x intervals

bind_sets <- function(first_percentile, second_percentile) {
first_percentile$percentile <- "Top 10%"
second_percentile$percentile <- "Top 20%"
rbind(first_percentile, second_percentile)
}
merlin_species_data <- bind_sets(merlin_10_data, merlin_20_data)
birdlife_species_data <- bind_sets(birdlife_10_data, birdlife_20_data)
either_species_data <- bind_sets(either_10_data, either_20_data)
both_species_data <- bind_sets(both_10_data, both_20_data)
diff_set <- function(first_percentile, second_percentile) {
second_percentile$response_20 <- second_percentile$response
result <- right_join(first_percentile, second_percentile[,c("niche_name", "response_20")], by = c("niche_name"))
result$diff <- result$response_20 - result$response
result$increase <- result$diff / result$response_20
result$increase[is.na(result$increase)] = 0
result$response_10 <- result$response
result[,c("response_10", "response_20", "diff", "increase", "foraging_niche", "trophic_niche", "is_nocturnal", "pc1", "pc2", "pc3", "pc4", "total_species")]
}
merlin_diff_data <- diff_set(merlin_10_data, merlin_20_data)
birdlife_diff_data <- diff_set(birdlife_10_data, birdlife_20_data)
either_diff_data <- diff_set(either_10_data, either_20_data)
both_diff_data <- diff_set(both_10_data, both_20_data)
merlin_diff_data
ggplot(merlin_species_data, aes(x = response, y = trophic_niche, color = percentile)) + geom_boxplot() + theme_bw()

merlin_trophic_niche_niche_anova <- aov(response~trophic_niche + percentile + Error(niche_name), data=merlin_species_data)
summary(merlin_trophic_niche_niche_anova)
Error: niche_name
Df Sum Sq Mean Sq F value Pr(>F)
trophic_niche 9 1.762 0.1958 1.679 0.0943 .
Residuals 258 30.084 0.1166
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Error: Within
Df Sum Sq Mean Sq F value Pr(>F)
percentile 1 1.508 1.5077 59.65 2.29e-13 ***
Residuals 267 6.749 0.0253
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
merlin_trophic_niche_niche_anova_i <- aov(response~trophic_niche * percentile + Error(niche_name), data=merlin_species_data)
summary(merlin_trophic_niche_niche_anova_i)
Error: niche_name
Df Sum Sq Mean Sq F value Pr(>F)
trophic_niche 9 1.762 0.1958 1.679 0.0943 .
Residuals 258 30.084 0.1166
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Error: Within
Df Sum Sq Mean Sq F value Pr(>F)
percentile 1 1.508 1.5077 69.821 4.05e-15 ***
trophic_niche:percentile 9 1.177 0.1308 6.057 1.03e-07 ***
Residuals 258 5.571 0.0216
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
pairwise.wilcox.test(merlin_diff_data$increase, merlin_diff_data$trophic_niche)
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
cannot compute exact p-value with ties
Pairwise comparisons using Wilcoxon rank sum test with continuity correction
data: merlin_diff_data$increase and merlin_diff_data$trophic_niche
Aquatic predator Frugivore Granivore Herbivore aquatic Herbivore terrestrial Invertivore Nectarivore Omnivore Scavenger
Frugivore 0.5331 - - - - - - - -
Granivore 1.0000 1.0000 - - - - - - -
Herbivore aquatic 1.0000 0.1167 1.0000 - - - - - -
Herbivore terrestrial 1.0000 1.0000 1.0000 1.0000 - - - - -
Invertivore 0.0076 1.0000 1.0000 0.0051 1.0000 - - - -
Nectarivore 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 - - -
Omnivore 0.2684 1.0000 1.0000 0.0679 1.0000 1.0000 1.0000 - -
Scavenger 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 -
Vertivore 1.0000 1.0000 1.0000 0.5929 1.0000 1.0000 1.0000 1.0000 1.0000
P value adjustment method: holm
library(multcomp)
merlin_increase_tropic_niche_anova <-aov(increase~trophic_niche, data=merlin_diff_data)
summary(merlin_increase_tropic_niche_anova)
Df Sum Sq Mean Sq F value Pr(>F)
trophic_niche 9 3.941 0.4379 3.689 0.000229 ***
Residuals 258 30.629 0.1187
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
merlin_increase_tropic_niche_tukey <- cld(glht(merlin_increase_tropic_niche_anova, linfct=mcp(trophic_niche="Tukey")))
Warning in RET$pfunction("adjusted", ...) :
Completion with error > abseps
Warning in RET$pfunction("adjusted", ...) :
Completion with error > abseps
Warning in RET$pfunction("adjusted", ...) :
Completion with error > abseps
Warning in RET$pfunction("adjusted", ...) :
Completion with error > abseps
Warning in RET$pfunction("adjusted", ...) :
Completion with error > abseps
Warning in RET$pfunction("adjusted", ...) :
Completion with error > abseps
Warning in RET$pfunction("adjusted", ...) :
Completion with error > abseps
Warning in RET$pfunction("adjusted", ...) :
Completion with error > abseps
merlin_increase_tropic_niche_tukey
Aquatic predator Frugivore Granivore Herbivore aquatic Herbivore terrestrial Invertivore Nectarivore Omnivore
"bc" "ab" "ac" "c" "ac" "a" "ac" "ab"
Scavenger Vertivore
"ac" "ac"
plot(merlin_increase_tropic_niche_tukey)

with.tukey.label.as.group <- function(tukey, dataset, join_by) {
labels <- data.frame(tukey$mcletters$Letters)
labels$category <- rownames(labels)
colnames(labels) <- c("group", "category")
left_join(dataset, labels, by = join_by)
}
merlin_diff_data1 <- with.tukey.label.as.group(merlin_increase_tropic_niche_tukey, merlin_diff_data, c("trophic_niche" = "category"))
merlin_diff_data1
table(merlin_diff_data1$trophic_niche)
Aquatic predator Frugivore Granivore Herbivore aquatic Herbivore terrestrial Invertivore Nectarivore Omnivore
58 25 10 15 9 74 11 34
Scavenger Vertivore
3 29
ggplot(merlin_diff_data1, aes(x = increase, y = trophic_niche, color = group)) + geom_boxplot() + theme_bw()

ggplot(birdlife_species_data, aes(x = response, y = trophic_niche, color = percentile)) + geom_boxplot() + theme_bw()

birdlife_trophic_niche_niche_anova <- aov(response~trophic_niche + percentile + Error(niche_name), data=birdlife_species_data)
summary(birdlife_trophic_niche_niche_anova)
Error: niche_name
Df Sum Sq Mean Sq F value Pr(>F)
trophic_niche 9 1.696 0.1885 1.605 0.114
Residuals 258 30.292 0.1174
Error: Within
Df Sum Sq Mean Sq F value Pr(>F)
percentile 1 1.327 1.3274 60.18 1.84e-13 ***
Residuals 267 5.890 0.0221
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
birdlife_trophic_niche_niche_anova_i <- aov(response~trophic_niche * percentile + Error(niche_name), data=birdlife_species_data)
summary(birdlife_trophic_niche_niche_anova_i)
Error: niche_name
Df Sum Sq Mean Sq F value Pr(>F)
trophic_niche 9 1.696 0.1885 1.605 0.114
Residuals 258 30.292 0.1174
Error: Within
Df Sum Sq Mean Sq F value Pr(>F)
percentile 1 1.327 1.3274 64.018 4.19e-14 ***
trophic_niche:percentile 9 0.540 0.0600 2.893 0.00282 **
Residuals 258 5.350 0.0207
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
birdlife_increase_tropic_niche_anova <-aov(increase~trophic_niche, data=birdlife_diff_data)
summary(birdlife_increase_tropic_niche_anova)
Df Sum Sq Mean Sq F value Pr(>F)
trophic_niche 9 2.21 0.2453 1.791 0.0703 .
Residuals 258 35.35 0.1370
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
birdlife_increase_tropic_niche_tukey <- cld(glht(birdlife_increase_tropic_niche_anova, linfct=mcp(trophic_niche="Tukey")))
Warning in RET$pfunction("adjusted", ...) :
Completion with error > abseps
Warning in RET$pfunction("adjusted", ...) :
Completion with error > abseps
birdlife_increase_tropic_niche_tukey
Aquatic predator Frugivore Granivore Herbivore aquatic Herbivore terrestrial Invertivore Nectarivore Omnivore
"b" "ab" "ab" "ab" "ab" "a" "ab" "ab"
Scavenger Vertivore
"ab" "ab"
birdlife_diff_data1 <- with.tukey.label.as.group(birdlife_increase_tropic_niche_tukey, birdlife_diff_data, c("trophic_niche" = "category"))
ggplot(birdlife_diff_data1, aes(x = increase, y = trophic_niche, color = group)) + geom_boxplot() + theme_bw()

ggplot(either_species_data, aes(x = response, y = trophic_niche, color = percentile)) + geom_boxplot() + theme_bw()

ggplot(both_species_data, aes(x = response, y = trophic_niche, color = percentile)) + geom_boxplot() + theme_bw()

nrow(merlin_10_data[merlin_10_data$response > 0,])
[1] 96
nrow(merlin_20_data[merlin_20_data$response > 0,])
[1] 128
nrow(birdlife_10_data[birdlife_10_data$response > 0,])
[1] 87
nrow(birdlife_20_data[birdlife_20_data$response > 0,])
[1] 124
nrow(either_10_data[either_10_data$response > 0,])
[1] 94
nrow(either_20_data[either_20_data$response > 0,])
[1] 123
nrow(both_10_data[both_10_data$response > 0,])
[1] 91
nrow(both_20_data[both_20_data$response > 0,])
[1] 128
ggplot(merlin_species_data, aes(x = response, y = foraging_niche, color = percentile)) + geom_boxplot() + theme_bw()

interaction.plot(merlin_species_data$foraging_niche, merlin_species_data$percentile, merlin_species_data$response)

merlin_foraging_niche_anova <- aov(response~foraging_niche + percentile + Error(niche_name), data=merlin_species_data)
summary(merlin_foraging_niche_anova)
Error: niche_name
Df Sum Sq Mean Sq F value Pr(>F)
foraging_niche 32 4.894 0.1529 1.333 0.118
Residuals 235 26.952 0.1147
Error: Within
Df Sum Sq Mean Sq F value Pr(>F)
percentile 1 1.508 1.5077 59.65 2.29e-13 ***
Residuals 267 6.749 0.0253
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
merlin_foraging_niche_anova_i <- aov(response~foraging_niche * percentile + Error(niche_name), data=merlin_species_data)
summary(merlin_foraging_niche_anova_i)
Error: niche_name
Df Sum Sq Mean Sq F value Pr(>F)
foraging_niche 32 4.894 0.1529 1.333 0.118
Residuals 235 26.952 0.1147
Error: Within
Df Sum Sq Mean Sq F value Pr(>F)
percentile 1 1.508 1.5077 68.706 8.81e-15 ***
foraging_niche:percentile 32 1.591 0.0497 2.266 0.000275 ***
Residuals 235 5.157 0.0219
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
ggplot(birdlife_species_data, aes(x = response, y = foraging_niche, color = percentile)) + geom_boxplot() + theme_bw()

birdlife_foraging_niche_anova <- aov(response~foraging_niche + percentile + Error(niche_name), data=birdlife_species_data)
summary(birdlife_foraging_niche_anova)
Error: niche_name
Df Sum Sq Mean Sq F value Pr(>F)
foraging_niche 32 5.519 0.1725 1.531 0.0401 *
Residuals 235 26.470 0.1126
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Error: Within
Df Sum Sq Mean Sq F value Pr(>F)
percentile 1 1.327 1.3274 60.18 1.84e-13 ***
Residuals 267 5.890 0.0221
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
birdlife_foraging_niche_anova_i <- aov(response~foraging_niche * percentile + Error(niche_name), data=birdlife_species_data)
summary(birdlife_foraging_niche_anova_i)
Error: niche_name
Df Sum Sq Mean Sq F value Pr(>F)
foraging_niche 32 5.519 0.1725 1.531 0.0401 *
Residuals 235 26.470 0.1126
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Error: Within
Df Sum Sq Mean Sq F value Pr(>F)
percentile 1 1.327 1.3274 67.870 1.22e-14 ***
foraging_niche:percentile 32 1.293 0.0404 2.066 0.00118 **
Residuals 235 4.596 0.0196
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
pc_axis_figure <- function(dataset) {
annotate_figure(
ggarrange(
ggplot(dataset, aes(x = pc1, y = log(response), color = percentile)) + geom_point(alpha = 0.5) + geom_smooth(method = "lm", se = FALSE) + theme_bw() + rremove("ylab"),
ggplot(dataset, aes(x = pc2, y = log(response), color = percentile)) + geom_point(alpha = 0.5) + geom_smooth(method = "lm", se = FALSE) + theme_bw() + rremove("ylab"),
ggplot(dataset, aes(x = pc3, y = log(response), color = percentile)) + geom_point(alpha = 0.5) + geom_smooth(method = "lm", se = FALSE) + theme_bw() + rremove("ylab"),
ggplot(dataset, aes(x = pc4, y = log(response), color = percentile)) + geom_point(alpha = 0.5) + geom_smooth(method = "lm", se = FALSE) + theme_bw() + rremove("ylab"),
nrow = 2, ncol = 2, common.legend = T, label.x = 0),
left = text_grob("log(response)", rot = 90))
}
pc_axis_figure(merlin_species_data)
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 312 rows containing non-finite values (stat_smooth).
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 312 rows containing non-finite values (stat_smooth).
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 312 rows containing non-finite values (stat_smooth).
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 312 rows containing non-finite values (stat_smooth).
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 312 rows containing non-finite values (stat_smooth).


library(lme4)
merlin_pc1_model = lmer(response ~ pc1 * percentile + (1|niche_name), data=merlin_species_data)
anova(merlin_pc1_model)
Analysis of Variance Table
npar Sum Sq Mean Sq F value
pc1 1 0.00042 0.00042 0.0169
percentile 1 1.50774 1.50774 59.9817
pc1:percentile 1 0.06215 0.06215 2.4724
summary(merlin_pc1_model)
Linear mixed model fit by REML ['lmerMod']
Formula: response ~ pc1 * percentile + (1 | niche_name)
Data: merlin_species_data
REML criterion at convergence: -8.6
Scaled residuals:
Min 1Q Median 3Q Max
-2.4461 -0.5197 0.0155 0.1840 3.3433
Random effects:
Groups Name Variance Std.Dev.
niche_name (Intercept) 0.04729 0.2175
Residual 0.02514 0.1585
Number of obs: 536, groups: niche_name, 268
Fixed effects:
Estimate Std. Error t value
(Intercept) 0.117739 0.022322 5.275
pc1 -0.005011 0.006481 -0.773
percentileTop 20% 0.086293 0.018597 4.640
pc1:percentileTop 20% 0.008490 0.005399 1.572
Correlation of Fixed Effects:
(Intr) pc1 prT20%
pc1 -0.676
prcntlTp20% -0.417 0.282
pc1:prcT20% 0.282 -0.417 -0.676
merlin_pc2_model = lmer(response ~ pc2 * percentile + (1|niche_name), data=merlin_species_data)
anova(merlin_pc2_model)
Analysis of Variance Table
npar Sum Sq Mean Sq F value
pc2 1 0.01486 0.01486 0.5864
percentile 1 1.50774 1.50774 59.5009
pc2:percentile 1 0.00812 0.00812 0.3203
summary(merlin_pc2_model)
Linear mixed model fit by REML ['lmerMod']
Formula: response ~ pc2 * percentile + (1 | niche_name)
Data: merlin_species_data
REML criterion at convergence: -11.2
Scaled residuals:
Min 1Q Median 3Q Max
-2.3691 -0.5150 0.0879 0.1354 3.3292
Random effects:
Groups Name Variance Std.Dev.
niche_name (Intercept) 0.04706 0.2169
Residual 0.02534 0.1592
Number of obs: 536, groups: niche_name, 268
Fixed effects:
Estimate Std. Error t value
(Intercept) 0.104389 0.016836 6.200
pc2 -0.008532 0.018597 -0.459
percentileTop 20% 0.104347 0.014086 7.408
pc2:percentileTop 20% -0.008805 0.015559 -0.566
Correlation of Fixed Effects:
(Intr) pc2 prT20%
pc2 0.217
prcntlTp20% -0.418 -0.091
pc2:prcT20% -0.091 -0.418 0.217
merlin_pc3_model = lmer(response ~ pc3 * percentile + (1|niche_name), data=merlin_species_data)
anova(merlin_pc3_model)
Analysis of Variance Table
npar Sum Sq Mean Sq F value
pc3 1 0.00044 0.00044 0.0187
percentile 1 1.50774 1.50774 63.7963
pc3:percentile 1 0.46195 0.46195 19.5464
summary(merlin_pc3_model)
Linear mixed model fit by REML ['lmerMod']
Formula: response ~ pc3 * percentile + (1 | niche_name)
Data: merlin_species_data
REML criterion at convergence: -30.5
Scaled residuals:
Min 1Q Median 3Q Max
-2.8609 -0.4057 -0.0338 0.2719 3.7473
Random effects:
Groups Name Variance Std.Dev.
niche_name (Intercept) 0.04804 0.2192
Residual 0.02363 0.1537
Number of obs: 536, groups: niche_name, 268
Fixed effects:
Estimate Std. Error t value
(Intercept) 0.10758 0.01638 6.568
pc3 -0.04333 0.02594 -1.670
percentileTop 20% 0.10282 0.01330 7.730
pc3:percentileTop 20% 0.09314 0.02107 4.421
Correlation of Fixed Effects:
(Intr) pc3 prT20%
pc3 -0.055
prcntlTp20% -0.406 0.022
pc3:prcT20% 0.022 -0.406 -0.055
merlin_pc4_model = lmer(response ~ pc4 * percentile + (1|niche_name), data=merlin_species_data)
anova(merlin_pc4_model)
Analysis of Variance Table
npar Sum Sq Mean Sq F value
pc4 1 0.06576 0.06576 2.6061
percentile 1 1.50774 1.50774 59.7558
pc4:percentile 1 0.03687 0.03687 1.4612
summary(merlin_pc4_model)
Linear mixed model fit by REML ['lmerMod']
Formula: response ~ pc4 * percentile + (1 | niche_name)
Data: merlin_species_data
REML criterion at convergence: -17
Scaled residuals:
Min 1Q Median 3Q Max
-2.4101 -0.5034 0.0731 0.1400 3.4938
Random effects:
Groups Name Variance Std.Dev.
niche_name (Intercept) 0.04666 0.2160
Residual 0.02523 0.1588
Number of obs: 536, groups: niche_name, 268
Fixed effects:
Estimate Std. Error t value
(Intercept) 0.10678 0.01640 6.513
pc4 0.03400 0.03543 0.960
percentileTop 20% 0.10683 0.01374 7.777
pc4:percentileTop 20% 0.03588 0.02969 1.209
Correlation of Fixed Effects:
(Intr) pc4 prT20%
pc4 0.046
prcntlTp20% -0.419 -0.019
pc4:prcT20% -0.019 -0.419 0.046
pc_axis_figure(birdlife_species_data)
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 325 rows containing non-finite values (stat_smooth).
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 325 rows containing non-finite values (stat_smooth).
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 325 rows containing non-finite values (stat_smooth).
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 325 rows containing non-finite values (stat_smooth).
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 325 rows containing non-finite values (stat_smooth).


ggplot(merlin_species_data, aes(x = response, y = is_nocturnal, color = percentile)) + geom_boxplot() + theme_bw()

merlin_nocturnal_anova <- aov(response~is_nocturnal + percentile + Error(niche_name), data=merlin_species_data)
summary(merlin_nocturnal_anova)
Error: niche_name
Df Sum Sq Mean Sq F value Pr(>F)
is_nocturnal 1 0.462 0.4615 3.912 0.049 *
Residuals 266 31.384 0.1180
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Error: Within
Df Sum Sq Mean Sq F value Pr(>F)
percentile 1 1.508 1.5077 59.65 2.29e-13 ***
Residuals 267 6.749 0.0253
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
merlin_nocturnal_anova_i <- aov(response~is_nocturnal * percentile + Error(niche_name), data=merlin_species_data)
summary(merlin_nocturnal_anova_i)
Error: niche_name
Df Sum Sq Mean Sq F value Pr(>F)
is_nocturnal 1 0.462 0.4615 3.912 0.049 *
Residuals 266 31.384 0.1180
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Error: Within
Df Sum Sq Mean Sq F value Pr(>F)
percentile 1 1.508 1.5077 60.685 1.51e-13 ***
is_nocturnal:percentile 1 0.140 0.1396 5.618 0.0185 *
Residuals 266 6.609 0.0248
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
ggplot(birdlife_species_data, aes(x = response, y = is_nocturnal, color = percentile)) + geom_boxplot() + theme_bw()

birdlife_nocturnal_anova <- aov(response~is_nocturnal + percentile + Error(niche_name), data=birdlife_species_data)
summary(birdlife_nocturnal_anova)
Error: niche_name
Df Sum Sq Mean Sq F value Pr(>F)
is_nocturnal 1 0.20 0.1982 1.658 0.199
Residuals 266 31.79 0.1195
Error: Within
Df Sum Sq Mean Sq F value Pr(>F)
percentile 1 1.327 1.3274 60.18 1.84e-13 ***
Residuals 267 5.890 0.0221
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
birdlife_nocturnal_anova_i <- aov(response~is_nocturnal * percentile + Error(niche_name), data=birdlife_species_data)
summary(birdlife_nocturnal_anova_i)
Error: niche_name
Df Sum Sq Mean Sq F value Pr(>F)
is_nocturnal 1 0.20 0.1982 1.658 0.199
Residuals 266 31.79 0.1195
Error: Within
Df Sum Sq Mean Sq F value Pr(>F)
percentile 1 1.327 1.3274 60.370 1.72e-13 ***
is_nocturnal:percentile 1 0.041 0.0407 1.852 0.175
Residuals 266 5.849 0.0220
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
| Investigation of percentiles and presence |
ggplot(merlin_species_data, aes(x = total_species, y = log(response), color = percentile)) + geom_point(alpha = 0.5) + geom_smooth(method = "lm", se = FALSE) + theme_bw()
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 312 rows containing non-finite values (stat_smooth).

merlin_species_count_model = lmer(response ~ total_species * percentile + (1|niche_name), data=merlin_species_data)
anova(merlin_species_count_model)
Analysis of Variance Table
npar Sum Sq Mean Sq F value
total_species 1 0.00052 0.00052 0.0206
percentile 1 1.50774 1.50774 59.4316
total_species:percentile 1 0.00026 0.00026 0.0103
summary(merlin_species_count_model)
Linear mixed model fit by REML ['lmerMod']
Formula: response ~ total_species * percentile + (1 | niche_name)
Data: merlin_species_data
REML criterion at convergence: 8.6
Scaled residuals:
Min 1Q Median 3Q Max
-2.3523 -0.5462 0.1109 0.1216 3.2582
Random effects:
Groups Name Variance Std.Dev.
niche_name (Intercept) 0.04717 0.2172
Residual 0.02537 0.1593
Number of obs: 536, groups: niche_name, 268
Fixed effects:
Estimate Std. Error t value
(Intercept) 1.064e-01 1.690e-02 6.295
total_species -1.420e-05 1.612e-04 -0.088
percentileTop 20% 1.064e-01 1.414e-02 7.527
total_species:percentileTop 20% -1.367e-05 1.348e-04 -0.101
Correlation of Fixed Effects:
(Intr) ttl_sp prT20%
total_specs -0.229
prcntlTp20% -0.418 0.096
ttl_sp:T20% 0.096 -0.418 -0.229
birdlife_species_count_model = lmer(response ~ total_species * percentile + (1|niche_name), data=birdlife_species_data)
anova(birdlife_species_count_model)
Analysis of Variance Table
npar Sum Sq Mean Sq F value
total_species 1 0.0000 0.0000 0.0001
percentile 1 1.3274 1.3274 59.9531
total_species:percentile 1 0.0000 0.0000 0.0001
summary(birdlife_species_count_model)
Linear mixed model fit by REML ['lmerMod']
Formula: response ~ total_species * percentile + (1 | niche_name)
Data: birdlife_species_data
REML criterion at convergence: -26.3
Scaled residuals:
Min 1Q Median 3Q Max
-2.5919 -0.5189 0.0633 0.1497 3.4600
Random effects:
Groups Name Variance Std.Dev.
niche_name (Intercept) 0.04906 0.2215
Residual 0.02214 0.1488
Number of obs: 536, groups: niche_name, 268
Fixed effects:
Estimate Std. Error t value
(Intercept) 9.946e-02 1.675e-02 5.939
total_species 9.392e-07 1.597e-04 0.006
percentileTop 20% 9.949e-02 1.321e-02 7.534
total_species:percentileTop 20% 1.518e-06 1.260e-04 0.012
Correlation of Fixed Effects:
(Intr) ttl_sp prT20%
total_specs -0.229
prcntlTp20% -0.394 0.090
ttl_sp:T20% 0.090 -0.394 -0.229
merlin_species_data$present <- merlin_species_data$response > 0

merlin_present_model = lmer(present ~ log(total_species) * percentile + (1|niche_name), data=merlin_species_data)
anova(merlin_present_model)
Analysis of Variance Table
npar Sum Sq Mean Sq F value
log(total_species) 1 7.6804 7.6804 145.5124
percentile 1 1.9104 1.9104 36.1952
log(total_species):percentile 1 0.0496 0.0496 0.9393
summary(merlin_present_model)
Linear mixed model fit by REML ['lmerMod']
Formula: present ~ log(total_species) * percentile + (1 | niche_name)
Data: merlin_species_data
REML criterion at convergence: 410.7
Scaled residuals:
Min 1Q Median 3Q Max
-2.25242 -0.44048 0.02734 0.24296 2.14911
Random effects:
Groups Name Variance Std.Dev.
niche_name (Intercept) 0.11259 0.3356
Residual 0.05278 0.2297
Number of obs: 536, groups: niche_name, 268
Fixed effects:
Estimate Std. Error t value
(Intercept) 0.10521 0.03325 3.164
log(total_species) 0.19281 0.01685 11.446
percentileTop 20% 0.13652 0.02657 5.139
log(total_species):percentileTop 20% -0.01304 0.01346 -0.969
Correlation of Fixed Effects:
(Intr) lg(t_) prT20%
lg(ttl_spc) -0.665
prcntlTp20% -0.399 0.266
lg(t_):T20% 0.266 -0.399 -0.665
assign_niche_appearance_factor <- function(dataset) {
dataset$niche_appearance = '> 20%'
dataset$niche_appearance[dataset$response_20 > 0] = '10% - 20%'
dataset$niche_appearance[dataset$response_10 > 0] = '< 10%'
dataset$niche_appearance <- factor(dataset$niche_appearance, levels = c("< 10%", "10% - 20%", "> 20%"))
dataset
}
merlin_diff_data <- assign_niche_appearance_factor(merlin_diff_data)
ggplot(merlin_diff_data, aes(fill=niche_appearance, y=trophic_niche)) +
geom_bar()

load_ever_data <- function(pool) {
response_name <- paste(pool, 'ever', 'perc', 'ratio', sep = '_')
dataset <- data_for_response(response_name)
dataset$present <- 'Yes'
dataset$present[dataset$response == 0] <- 'No'
dataset$present <- factor(dataset$present, levels = c("Yes", "No"))
dataset
}
merlin_ever_data <- load_ever_data('merlin')
── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
.default = col_double(),
niche_name = col_character(),
foraging_niche = col_character(),
trophic_niche = col_character(),
is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
merlin_ever_data
ggplot(merlin_ever_data, aes(fill=present, y=trophic_niche)) +
geom_bar()

birdlife_diff_data <- assign_niche_appearance_factor(birdlife_diff_data)
ggplot(birdlife_diff_data, aes(fill=niche_appearance, y=trophic_niche)) +
geom_bar()

birdlife_ever_data <- load_ever_data('birdlife')
── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
.default = col_double(),
niche_name = col_character(),
foraging_niche = col_character(),
trophic_niche = col_character(),
is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
ggplot(merlin_ever_data, aes(fill=present, y=trophic_niche)) +
geom_bar()

| PCA Variation with presence |
ggplot(merlin_ever_data, aes(color = present, x = pc1, y = trophic_niche)) +
geom_violin() + geom_jitter(aes(group=present, size = total_species), position=position_jitterdodge()) + theme_bw() +
theme(legend.position="bottom", legend.title=element_text(size=9), legend.text=element_text(size=8), legend.key.size = unit(1,"line")) +
guides(color=guide_legend(title="Present in any city?"), size=guide_legend(title="Niche size")) +
ylab("Trophic Niche") + xlab("PC1: Body size") + labs(title = "Merlin Regional Pool")
ggsave("species_analysis_pc1_merlin.jpg")
Saving 7.29 x 4.51 in image

ggplot(merlin_diff_data, aes(color = niche_appearance, x = pc1, y = trophic_niche)) +
geom_violin()
Warning: Groups with fewer than two data points have been dropped.
Warning: Groups with fewer than two data points have been dropped.
Warning: Groups with fewer than two data points have been dropped.
Warning: Groups with fewer than two data points have been dropped.
Warning: Groups with fewer than two data points have been dropped.




ggplot(birdlife_ever_data, aes(color = present, x = pc1, y = trophic_niche)) +
geom_violin() + geom_jitter(aes(group=present, size = total_species), position=position_jitterdodge()) + theme_bw() +
theme(legend.position="bottom", legend.title=element_text(size=9), legend.text=element_text(size=8), legend.key.size = unit(1,"line")) +
guides(color=guide_legend(title="Present in any city?"), size=guide_legend(title="Niche size")) +
ylab("Trophic Niche") + xlab("PC1: Body size") + labs(title = "Birdlife Regional Pool")
ggsave("species_analysis_pc1_birdlife.jpg")

- Niches recorded present in at least one city.
- Given species ranked by percentage of cities populated given they are present in regional pool; This shows niches present with the top 10% of the most urbanised species (red), the top 20% of the most urbanised species (red + green), and then the remaining niches (blue). This approximates to the niches that would be present in the bottom 25% performing hotspots (red), the bottom 75% performing hotspots (red + green), and then the niches at the highest performing hotspots or niches that are never present (blue).

- The redundancy/fullness of the niches that are present in cities with 10% of the most urbanised species, and the redundancy/fullness of the niches that are present in cities with 20% of the most urbanised species.
- The percentage increase in redundancy/fullness of niches between the top 10% of most urbanised species and the top 20% of most urbanised species, grouped using Tukey based on an anova of the percentage increase given the tropic niche. This shows the amount of redundancy that is increased from the bottom 25% performing hotspots (hotspots with 10% of regional pool) and the bottom 75% of performing hotspots (hotspots with 20% of regional pool).
jpeg("species_plot1.jpg", width = 800, height = 600)
species_plot1
dev.off()
jpeg("species_plot2.jpg", width = 800, height = 600)
species_plot2
dev.off()
| Trophic Niche Accumulation |
merlin_accumulation = ggplot(accumulation, aes(x = percent, y = merlin_niche_count)) +
geom_line(linetype = "dotted") +
geom_line(aes(linetype = merlin_remaining_species), na.value = "dash") +
scale_linetype_manual(values=c("blank", "solid"), guide = "none") +
geom_hline(data = . %>% group_by(trophic_niche) %>% filter(merlin_niche_count == max(merlin_niche_count)), aes(yintercept = merlin_niche_count), color = "blue", size = 0.25, linetype = "dashed") +
theme_bw() +
theme(legend.position = "bottom", strip.text = element_text(size = 6), axis.text.x = element_text(angle = 90, size = 6), axis.text.y = element_text(size = 6)) +
facet_wrap (~ trophic_niche) +
xlab("Percentage of all Species") +
ylab("Number of Niches") +
labs(title = "Merlin Niche Accumulation")
Warning: Ignoring unknown parameters: na.value
merlin_accumulation

birdlife_accumulation = ggplot(accumulation, aes(x = percent, y = birdlife_niche_count)) +
geom_line(linetype = "dotted") +
geom_line(aes(linetype = birdlife_remaining_species), na.value = "dash") +
scale_linetype_manual(values=c("blank", "solid"), guide = "none") +
geom_hline(data = . %>% group_by(trophic_niche) %>% filter(birdlife_niche_count == max(birdlife_niche_count)), aes(yintercept = birdlife_niche_count), color = "blue", size = 0.25, linetype = "dashed") +
theme_bw() +
theme(legend.position = "bottom", strip.text = element_text(size = 6), axis.text.x = element_text(angle = 90, size = 6), axis.text.y = element_text(size = 6)) +
facet_wrap (~ trophic_niche) +
xlab("Percentage of all Species") +
ylab("Number of Niches") +
labs(title = "Birdlife Niche Accumulation")
Warning: Ignoring unknown parameters: na.value
birdlife_accumulation

annotate_figure(
ggarrange(merlin_accumulation + rremove("xlab") + rremove("ylab"),
birdlife_accumulation + rremove("xlab") + rremove("ylab"),
ncol = 2, label.x = 0),
left = text_grob("Number of Niches Present", rot = 90),
bottom = text_grob("Percentage of all Species - ranked by urbanisation"))
ggsave("trophic_niche_accumlation.jpg")
Saving 7.29 x 4.51 in image

ggplot(accumulation, aes(x = percent, y = birdlife_niche_count)) +
geom_line(linetype = "dotted") +
geom_line(aes(linetype = birdlife_remaining_species), na.value = "dash") +
scale_linetype_manual(values=c("blank", "solid"), guide = "none") +
geom_hline(data = . %>% group_by(trophic_niche) %>% filter(birdlife_niche_count == max(birdlife_niche_count)), aes(yintercept = birdlife_niche_count), color = "blue", size = 0.25, linetype = "dashed") +
theme_bw() +
theme(legend.position = "bottom", strip.text = element_text(size = 6), axis.text.x = element_text(angle = 90, size = 6), axis.text.y = element_text(size = 6)) +
facet_wrap (~ factor(trophic_niche, levels = c("Invertivore", "Aquatic predator", "Omnivore", "Vertivore", "Frugivore", "Herbivore aquatic", "Granivore", "Herbivore terrestrial", "Nectarivore", "Scavenger")), scales = "free") +
xlab("Percentage of all Species") +
ylab("Number of Niches") +
labs(title = "Birdlife Niche Accumulation") +
xlim(0, 50)
Warning: Ignoring unknown parameters: na.value
Warning: Removed 10 row(s) containing missing values (geom_path).
Warning: Removed 10 row(s) containing missing values (geom_path).

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQpgYGB7cn0KbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShiaWdycXVlcnkpCmxpYnJhcnkoTXVNSW4pCmxpYnJhcnkoZ2dwbG90MikKCmxpYnJhcnkoZ2dwdWJyKQpgYGAKCmBgYHtyfQpyZXNwb25zZSA8LSB0cnkoc3lzdGVtKCd+L2dvb2dsZS1jbG91ZC1zZGsvYmluL2djbG91ZCBwcm9qZWN0cyBsaXN0IC0tcXVpZXQnLCBpbnRlcm4gPSBUKSkKcHJvamVjdGlkIDwtIHN0cnNwbGl0KHJlc3BvbnNlWzJdLCAiICIpW1sxXV1bMV0KYGBgCgpgYGB7cn0Kb3B0aW9ucyhuYS5hY3Rpb24gPSAibmEuZmFpbCIpIApgYGAKCmBgYHtyfQpzb3VyY2UoIi4vZHJlZGdlX2Z1bmN0aW9ucy5SIikKYGBgCgpgYGB7cn0KZHJlZGdlX2FuZF9zdWJzZXQgPC0gZnVuY3Rpb24oZGF0YSkgewogIG1vZGVsIDwtIGxtKAogICAgcmVzcG9uc2UgfiBmb3JhZ2luZ19uaWNoZSArIHRyb3BoaWNfbmljaGUgKyBpc19ub2N0dXJuYWwgKyBwYzEgKyBwYzIgKyBwYzMgKyBwYzQgKyB0b3RhbF9zcGVjaWVzLAogICAgZGF0YT1kYXRhCiAgKQogIGRyZWRnZV9yZXN1bHQgPC0gZHJlZGdlKG1vZGVsKQogIHN1bW1hcnkobW9kZWwuYXZnKGRyZWRnZV9yZXN1bHQsIHN1YnNldCA9IGRlbHRhIDwgMTApKQp9CmBgYAoKYGBge3J9CmxvYWRfbmljaGVfZGF0YSA8LSBmdW5jdGlvbigpIHsKICBmaWxlbmFtZSA8LSAnc3BlY2llc19hbmFseXNpc19jYWNoZS5jc3YnCiAgCiAgaWYgKCFmaWxlLmV4aXN0cyhmaWxlbmFtZSkpIHsKICAgIAogICAgc3FsIDwtICIKICAgICAgICBTRUxFQ1QgCiAgICAgICAgICBuaWNoZV9uYW1lLAogICAgICAgICAgZm9yYWdpbmdfbmljaGUsIAogICAgICAgICAgdHJvcGhpY19uaWNoZSwgCiAgICAgICAgICBpc19ub2N0dXJhbCwgCiAgICAgICAgICB0b3RhbF9zcGVjaWVzLAogICAgICAgICAgbWVybGluXzEwX3BlcmNfcmF0aW8sIAogICAgICAgICAgbWVybGluXzIwX3BlcmNfcmF0aW8sCiAgICAgICAgICBtZXJsaW5fZXZlcl9wZXJjX3JhdGlvLAogICAgICAgICAgYmlyZGxpZmVfMTBfcGVyY19yYXRpbywgCiAgICAgICAgICBiaXJkbGlmZV8yMF9wZXJjX3JhdGlvLAogICAgICAgICAgYmlyZGxpZmVfZXZlcl9wZXJjX3JhdGlvLAogICAgICAgICAgZWl0aGVyXzEwX3BlcmNfcmF0aW8sIAogICAgICAgICAgZWl0aGVyXzIwX3BlcmNfcmF0aW8sIAogICAgICAgICAgZWl0aGVyX2V2ZXJfcGVyY19yYXRpbywKICAgICAgICAgIGJvdGhfMTBfcGVyY19yYXRpbywgCiAgICAgICAgICBib3RoXzIwX3BlcmNfcmF0aW8sCiAgICAgICAgICBib3RoX2V2ZXJfcGVyY19yYXRpbywKICAgICAgICAgIGJvZHlfbW9ycGhzcGFjZS5wYzEubWVhbiBBUyBwYzEsIAogICAgICAgICAgYm9keV9tb3JwaHNwYWNlLnBjMi5tZWFuIEFTIHBjMiwgCiAgICAgICAgICBib2R5X21vcnBoc3BhY2UucGMzLm1lYW4gQVMgcGMzLCAKICAgICAgICAgIGJvZHlfbW9ycGhzcGFjZS5wYzQubWVhbiBBUyBwYzQKICAgICAgICBGUk9NIGBlbmRsZXNzLW1hdHRlci0yOTcyMTQubW9kZWwyLm5pY2hlX2FuYWx5c2lzX21vZGVsYCBMSU1JVCAxMDAwIAogICAgIgogIAogICAgdGIgPC0gYnFfcHJvamVjdF9xdWVyeShwcm9qZWN0aWQsIHNxbCkKCiAgICBkYXRhIDwtIGJxX3RhYmxlX2Rvd25sb2FkKHRiKQogICAgd3JpdGVfY3N2KGRhdGEsIGZpbGVuYW1lKQogIH0KICAKICBkYXRhIDwtIHJlYWRfY3N2KGZpbGVuYW1lKQogIAogIGRhdGFbaXMubmEoZGF0YSRmb3JhZ2luZ19uaWNoZSksXSRmb3JhZ2luZ19uaWNoZSA8LSAnT21uaXZvcmUnCiAgCiAgZGF0YSRmb3JhZ2luZ19uaWNoZSA9IGFzLmZhY3RvcihkYXRhJGZvcmFnaW5nX25pY2hlKQogIGRhdGEkdHJvcGhpY19uaWNoZSA9IGFzLmZhY3RvcihkYXRhJHRyb3BoaWNfbmljaGUpCiAgZGF0YSRpc19ub2N0dXJuYWwgPSBhcy5mYWN0b3IoZGF0YSRpc19ub2N0dXJhbCkKICAKICBkYXRhCn0KCmRhdGFfZm9yX3Jlc3BvbnNlIDwtIGZ1bmN0aW9uKGNvbHVtbl9uYW1lX2Zvcl9yZXNwb25zZSkgewogIGRhdGEgPC0gbG9hZF9uaWNoZV9kYXRhKCkKICBuYW1lcyhkYXRhKVtuYW1lcyhkYXRhKSA9PSBjb2x1bW5fbmFtZV9mb3JfcmVzcG9uc2VdIDwtICJyZXNwb25zZSIKICAKICBkYXRhWyxjKCJuaWNoZV9uYW1lIiwgInJlc3BvbnNlIiwgImZvcmFnaW5nX25pY2hlIiwgInRyb3BoaWNfbmljaGUiLCAiaXNfbm9jdHVybmFsIiwgInBjMSIsICJwYzIiLCAicGMzIiwgInBjNCIsICJ0b3RhbF9zcGVjaWVzIildCn0KYGBgCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KMC4yNSBQZXJjZW50aWxlIC0gMTAlIG9mIHNwZWNpZXMKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpgYGB7cn0KbWVybGluXzEwX2RhdGEgPC0gZGF0YV9mb3JfcmVzcG9uc2UoJ21lcmxpbl8xMF9wZXJjX3JhdGlvJykKbWVybGluXzEwX2RhdGEKYGBgCgoKYGBge3J9Cm1lcmxpbl8xMF9yZXN1bHQgPC0gZHJlZGdlX2FuZF9zdWJzZXQobWVybGluXzEwX2RhdGEpCm1lcmxpbl8xMF9zdW1tIDwtIG1vZGVsX3N1bW1hcnkoJ21lcmxpbl8xMCcsICdzcGVjaWVzJywgbWVybGluXzEwX3Jlc3VsdCkKbWVybGluXzEwX3N1bW0KYGBgCgpgYGB7cn0KYmlyZGxpZmVfMTBfZGF0YSA8LSBkYXRhX2Zvcl9yZXNwb25zZSgnYmlyZGxpZmVfMTBfcGVyY19yYXRpbycpCmJpcmRsaWZlXzEwX3Jlc3VsdCA8LSBkcmVkZ2VfYW5kX3N1YnNldChiaXJkbGlmZV8xMF9kYXRhKQpiaXJkbGlmZV8xMF9zdW1tIDwtIG1vZGVsX3N1bW1hcnkoJ2JpcmRsaWZlXzEwJywgJ3NwZWNpZXMnLCBiaXJkbGlmZV8xMF9yZXN1bHQpCmJpcmRsaWZlXzEwX3N1bW0KYGBgCgoKYGBge3J9CmJvdGhfMTBfZGF0YSA8LSBkYXRhX2Zvcl9yZXNwb25zZSgnYm90aF8xMF9wZXJjX3JhdGlvJykKYm90aF8xMF9yZXN1bHQgPC0gZHJlZGdlX2FuZF9zdWJzZXQoYm90aF8xMF9kYXRhKQpib3RoXzEwX3N1bW0gPC0gbW9kZWxfc3VtbWFyeSgnYm90aF8xMCcsICdzcGVjaWVzJywgYm90aF8xMF9yZXN1bHQpCmJvdGhfMTBfc3VtbQpgYGAKCgpgYGB7cn0KZWl0aGVyXzEwX2RhdGEgPC0gZGF0YV9mb3JfcmVzcG9uc2UoJ2VpdGhlcl8xMF9wZXJjX3JhdGlvJykKZWl0aGVyXzEwX3Jlc3VsdCA8LSBkcmVkZ2VfYW5kX3N1YnNldChlaXRoZXJfMTBfZGF0YSkKZWl0aGVyXzEwX3N1bW0gPC0gbW9kZWxfc3VtbWFyeSgnZWl0aGVyXzEwJywgJ3NwZWNpZXMnLCBlaXRoZXJfMTBfcmVzdWx0KQplaXRoZXJfMTBfc3VtbQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpGdWxsIHJlc3VsdCBmb3IgMTAlIG9mIHNwZWNpZXMKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCmBgYHtyfQphbGxfc3BlY2llc19yZXN1bHRzIDwtIGZ1bGxfam9pbihmdWxsX2pvaW4obWVybGluXzEwX3N1bW0sIGJpcmRsaWZlXzEwX3N1bW0pLCBmdWxsX2pvaW4oYm90aF8xMF9zdW1tLCBlaXRoZXJfMTBfc3VtbSkpCndyaXRlX2NzdihhbGxfc3BlY2llc19yZXN1bHRzLCAic3BlY2llc19hbmFseXNpc19yZXN1bHRfMTBfcGVyYy5jc3YiKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQowLjc1IFBlcmNlbnRpbGUgLSAyMCUgb2Ygc3BlY2llcwotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmBgYHtyfQptZXJsaW5fMjBfZGF0YSA8LSBkYXRhX2Zvcl9yZXNwb25zZSgnbWVybGluXzIwX3BlcmNfcmF0aW8nKQptZXJsaW5fMjBfcmVzdWx0IDwtIGRyZWRnZV9hbmRfc3Vic2V0KG1lcmxpbl8yMF9kYXRhKQptZXJsaW5fMjBfc3VtbSA8LSBtb2RlbF9zdW1tYXJ5KCdtZXJsaW5fMjAnLCAnc3BlY2llcycsIG1lcmxpbl8yMF9yZXN1bHQpCm1lcmxpbl8yMF9zdW1tCmBgYAoKYGBge3J9CmJpcmRsaWZlXzIwX2RhdGEgPC0gZGF0YV9mb3JfcmVzcG9uc2UoJ2JpcmRsaWZlXzIwX3BlcmNfcmF0aW8nKQpiaXJkbGlmZV8yMF9yZXN1bHQgPC0gZHJlZGdlX2FuZF9zdWJzZXQoYmlyZGxpZmVfMjBfZGF0YSkKYmlyZGxpZmVfMjBfc3VtbSA8LSBtb2RlbF9zdW1tYXJ5KCdiaXJkbGlmZV8yMCcsICdzcGVjaWVzJywgYmlyZGxpZmVfMjBfcmVzdWx0KQpiaXJkbGlmZV8yMF9zdW1tCmBgYAoKYGBge3J9CmJvdGhfMjBfZGF0YSA8LSBkYXRhX2Zvcl9yZXNwb25zZSgnYm90aF8yMF9wZXJjX3JhdGlvJykKYm90aF8yMF9yZXN1bHQgPC0gZHJlZGdlX2FuZF9zdWJzZXQoYm90aF8yMF9kYXRhKQpib3RoXzIwX3N1bW0gPC0gbW9kZWxfc3VtbWFyeSgnYm90aF8yMCcsICdzcGVjaWVzJywgYm90aF8yMF9yZXN1bHQpCmJvdGhfMjBfc3VtbQpgYGAKCmBgYHtyfQplaXRoZXJfMjBfZGF0YSA8LSBkYXRhX2Zvcl9yZXNwb25zZSgnZWl0aGVyXzIwX3BlcmNfcmF0aW8nKQplaXRoZXJfMjBfcmVzdWx0IDwtIGRyZWRnZV9hbmRfc3Vic2V0KGVpdGhlcl8yMF9kYXRhKQplaXRoZXJfMjBfc3VtbSA8LSBtb2RlbF9zdW1tYXJ5KCdlaXRoZXJfMjAnLCAnc3BlY2llcycsIGVpdGhlcl8yMF9yZXN1bHQpCmVpdGhlcl8yMF9zdW1tCmBgYAoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCkZ1bGwgcmVzdWx0IGZvciAxMCUgb2Ygc3BlY2llcwotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KYGBge3J9CmFsbF9zcGVjaWVzX3Jlc3VsdHMgPC0gZnVsbF9qb2luKGZ1bGxfam9pbihtZXJsaW5fMjBfc3VtbSwgYmlyZGxpZmVfMjBfc3VtbSksIGZ1bGxfam9pbihib3RoXzIwX3N1bW0sIGVpdGhlcl8yMF9zdW1tKSkKd3JpdGVfY3N2KGFsbF9zcGVjaWVzX3Jlc3VsdHMsICJzcGVjaWVzX2FuYWx5c2lzX3Jlc3VsdF8yMF9wZXJjLmNzdiIpCmBgYAoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCkNvbXBhcmluZyB0aGUgMiBwZXJjZW50aWxlcwotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmBgYHtyfQpnZ3Bsb3QobWVybGluXzEwX2RhdGEsIGFlcyh4ID0gcmVzcG9uc2UpKSArIGdlb21fYmFyKHdpZHRoID0gMC4xKQpgYGAKCmBgYHtyfQpiaW5kX3NldHMgPC0gZnVuY3Rpb24oZmlyc3RfcGVyY2VudGlsZSwgc2Vjb25kX3BlcmNlbnRpbGUpIHsKICBmaXJzdF9wZXJjZW50aWxlJHBlcmNlbnRpbGUgPC0gIlRvcCAxMCUiCiAgc2Vjb25kX3BlcmNlbnRpbGUkcGVyY2VudGlsZSA8LSAiVG9wIDIwJSIKICByYmluZChmaXJzdF9wZXJjZW50aWxlLCBzZWNvbmRfcGVyY2VudGlsZSkKfQoKbWVybGluX3NwZWNpZXNfZGF0YSA8LSBiaW5kX3NldHMobWVybGluXzEwX2RhdGEsICBtZXJsaW5fMjBfZGF0YSkKYmlyZGxpZmVfc3BlY2llc19kYXRhIDwtIGJpbmRfc2V0cyhiaXJkbGlmZV8xMF9kYXRhLCAgYmlyZGxpZmVfMjBfZGF0YSkKZWl0aGVyX3NwZWNpZXNfZGF0YSA8LSBiaW5kX3NldHMoZWl0aGVyXzEwX2RhdGEsICBlaXRoZXJfMjBfZGF0YSkKYm90aF9zcGVjaWVzX2RhdGEgPC0gYmluZF9zZXRzKGJvdGhfMTBfZGF0YSwgIGJvdGhfMjBfZGF0YSkKYGBgCgpgYGB7cn0KZGlmZl9zZXQgPC0gZnVuY3Rpb24oZmlyc3RfcGVyY2VudGlsZSwgc2Vjb25kX3BlcmNlbnRpbGUpIHsKICBzZWNvbmRfcGVyY2VudGlsZSRyZXNwb25zZV8yMCA8LSBzZWNvbmRfcGVyY2VudGlsZSRyZXNwb25zZQogIAogIHJlc3VsdCA8LSByaWdodF9qb2luKGZpcnN0X3BlcmNlbnRpbGUsIHNlY29uZF9wZXJjZW50aWxlWyxjKCJuaWNoZV9uYW1lIiwgInJlc3BvbnNlXzIwIildLCBieSA9IGMoIm5pY2hlX25hbWUiKSkKICByZXN1bHQkZGlmZiA8LSByZXN1bHQkcmVzcG9uc2VfMjAgLSByZXN1bHQkcmVzcG9uc2UKICByZXN1bHQkaW5jcmVhc2UgPC0gcmVzdWx0JGRpZmYgLyByZXN1bHQkcmVzcG9uc2VfMjAKICByZXN1bHQkaW5jcmVhc2VbaXMubmEocmVzdWx0JGluY3JlYXNlKV0gPSAwCiAgcmVzdWx0JHJlc3BvbnNlXzEwIDwtIHJlc3VsdCRyZXNwb25zZQogIHJlc3VsdFssYygicmVzcG9uc2VfMTAiLCAicmVzcG9uc2VfMjAiLCAiZGlmZiIsICJpbmNyZWFzZSIsICJmb3JhZ2luZ19uaWNoZSIsICJ0cm9waGljX25pY2hlIiwgImlzX25vY3R1cm5hbCIsICJwYzEiLCAicGMyIiwgInBjMyIsICJwYzQiLCAidG90YWxfc3BlY2llcyIpXQp9CgptZXJsaW5fZGlmZl9kYXRhIDwtIGRpZmZfc2V0KG1lcmxpbl8xMF9kYXRhLCAgbWVybGluXzIwX2RhdGEpCmJpcmRsaWZlX2RpZmZfZGF0YSA8LSBkaWZmX3NldChiaXJkbGlmZV8xMF9kYXRhLCAgYmlyZGxpZmVfMjBfZGF0YSkKZWl0aGVyX2RpZmZfZGF0YSA8LSBkaWZmX3NldChlaXRoZXJfMTBfZGF0YSwgIGVpdGhlcl8yMF9kYXRhKQpib3RoX2RpZmZfZGF0YSA8LSBkaWZmX3NldChib3RoXzEwX2RhdGEsICBib3RoXzIwX2RhdGEpCgptZXJsaW5fZGlmZl9kYXRhCmBgYAoKYGBge3J9CmdncGxvdChtZXJsaW5fc3BlY2llc19kYXRhLCBhZXMoeCA9IHJlc3BvbnNlLCB5ID0gdHJvcGhpY19uaWNoZSwgY29sb3IgPSBwZXJjZW50aWxlKSkgKyBnZW9tX2JveHBsb3QoKSArIHRoZW1lX2J3KCkKYGBgCgpgYGB7cn0KbWVybGluX3Ryb3BoaWNfbmljaGVfbmljaGVfYW5vdmEgPC0gYW92KHJlc3BvbnNlfnRyb3BoaWNfbmljaGUgKyBwZXJjZW50aWxlICsgRXJyb3IobmljaGVfbmFtZSksIGRhdGE9bWVybGluX3NwZWNpZXNfZGF0YSkKc3VtbWFyeShtZXJsaW5fdHJvcGhpY19uaWNoZV9uaWNoZV9hbm92YSkKCm1lcmxpbl90cm9waGljX25pY2hlX25pY2hlX2Fub3ZhX2kgPC0gYW92KHJlc3BvbnNlfnRyb3BoaWNfbmljaGUgKiBwZXJjZW50aWxlICsgRXJyb3IobmljaGVfbmFtZSksIGRhdGE9bWVybGluX3NwZWNpZXNfZGF0YSkKc3VtbWFyeShtZXJsaW5fdHJvcGhpY19uaWNoZV9uaWNoZV9hbm92YV9pKQpgYGAKCmBgYHtyfQpwYWlyd2lzZS53aWxjb3gudGVzdChtZXJsaW5fZGlmZl9kYXRhJGluY3JlYXNlLCBtZXJsaW5fZGlmZl9kYXRhJHRyb3BoaWNfbmljaGUpCmBgYApgYGB7cn0KbGlicmFyeShtdWx0Y29tcCkKbWVybGluX2luY3JlYXNlX3Ryb3BpY19uaWNoZV9hbm92YSA8LWFvdihpbmNyZWFzZX50cm9waGljX25pY2hlLCBkYXRhPW1lcmxpbl9kaWZmX2RhdGEpCnN1bW1hcnkobWVybGluX2luY3JlYXNlX3Ryb3BpY19uaWNoZV9hbm92YSkKCm1lcmxpbl9pbmNyZWFzZV90cm9waWNfbmljaGVfdHVrZXkgPC0gY2xkKGdsaHQobWVybGluX2luY3JlYXNlX3Ryb3BpY19uaWNoZV9hbm92YSwgbGluZmN0PW1jcCh0cm9waGljX25pY2hlPSJUdWtleSIpKSkKCm1lcmxpbl9pbmNyZWFzZV90cm9waWNfbmljaGVfdHVrZXkKYGBgCgpgYGB7cn0KcGxvdChtZXJsaW5faW5jcmVhc2VfdHJvcGljX25pY2hlX3R1a2V5KQpgYGAKYGBge3J9CndpdGgudHVrZXkubGFiZWwuYXMuZ3JvdXAgPC0gZnVuY3Rpb24odHVrZXksIGRhdGFzZXQsIGpvaW5fYnkpIHsKICBsYWJlbHMgPC0gZGF0YS5mcmFtZSh0dWtleSRtY2xldHRlcnMkTGV0dGVycykKICBsYWJlbHMkY2F0ZWdvcnkgPC0gcm93bmFtZXMobGFiZWxzKQogIGNvbG5hbWVzKGxhYmVscykgPC0gYygiZ3JvdXAiLCAiY2F0ZWdvcnkiKQogIAogIAogIGxlZnRfam9pbihkYXRhc2V0LCBsYWJlbHMsIGJ5ID0gam9pbl9ieSkKfQpgYGAKCmBgYHtyfQptZXJsaW5fZGlmZl9kYXRhMSA8LSB3aXRoLnR1a2V5LmxhYmVsLmFzLmdyb3VwKG1lcmxpbl9pbmNyZWFzZV90cm9waWNfbmljaGVfdHVrZXksIG1lcmxpbl9kaWZmX2RhdGEsIGMoInRyb3BoaWNfbmljaGUiID0gImNhdGVnb3J5IikpCm1lcmxpbl9kaWZmX2RhdGExCmBgYApgYGB7cn0KdGFibGUobWVybGluX2RpZmZfZGF0YTEkdHJvcGhpY19uaWNoZSkKYGBgCgpgYGB7cn0KZ2dwbG90KG1lcmxpbl9kaWZmX2RhdGExLCBhZXMoeCA9IGluY3JlYXNlLCB5ID0gdHJvcGhpY19uaWNoZSwgY29sb3IgPSBncm91cCkpICsgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZV9idygpCmBgYAoKYGBge3J9CmdncGxvdChiaXJkbGlmZV9zcGVjaWVzX2RhdGEsIGFlcyh4ID0gcmVzcG9uc2UsIHkgPSB0cm9waGljX25pY2hlLCBjb2xvciA9IHBlcmNlbnRpbGUpKSArIGdlb21fYm94cGxvdCgpICsgdGhlbWVfYncoKQpgYGAKCmBgYHtyfQpiaXJkbGlmZV90cm9waGljX25pY2hlX25pY2hlX2Fub3ZhIDwtIGFvdihyZXNwb25zZX50cm9waGljX25pY2hlICsgcGVyY2VudGlsZSArIEVycm9yKG5pY2hlX25hbWUpLCBkYXRhPWJpcmRsaWZlX3NwZWNpZXNfZGF0YSkKc3VtbWFyeShiaXJkbGlmZV90cm9waGljX25pY2hlX25pY2hlX2Fub3ZhKQoKYmlyZGxpZmVfdHJvcGhpY19uaWNoZV9uaWNoZV9hbm92YV9pIDwtIGFvdihyZXNwb25zZX50cm9waGljX25pY2hlICogcGVyY2VudGlsZSArIEVycm9yKG5pY2hlX25hbWUpLCBkYXRhPWJpcmRsaWZlX3NwZWNpZXNfZGF0YSkKc3VtbWFyeShiaXJkbGlmZV90cm9waGljX25pY2hlX25pY2hlX2Fub3ZhX2kpCmBgYAoKYGBge3J9CmJpcmRsaWZlX2luY3JlYXNlX3Ryb3BpY19uaWNoZV9hbm92YSA8LWFvdihpbmNyZWFzZX50cm9waGljX25pY2hlLCBkYXRhPWJpcmRsaWZlX2RpZmZfZGF0YSkKc3VtbWFyeShiaXJkbGlmZV9pbmNyZWFzZV90cm9waWNfbmljaGVfYW5vdmEpCgpiaXJkbGlmZV9pbmNyZWFzZV90cm9waWNfbmljaGVfdHVrZXkgPC0gY2xkKGdsaHQoYmlyZGxpZmVfaW5jcmVhc2VfdHJvcGljX25pY2hlX2Fub3ZhLCBsaW5mY3Q9bWNwKHRyb3BoaWNfbmljaGU9IlR1a2V5IikpKQoKYmlyZGxpZmVfaW5jcmVhc2VfdHJvcGljX25pY2hlX3R1a2V5CmBgYAoKYGBge3J9CmJpcmRsaWZlX2RpZmZfZGF0YTEgPC0gd2l0aC50dWtleS5sYWJlbC5hcy5ncm91cChiaXJkbGlmZV9pbmNyZWFzZV90cm9waWNfbmljaGVfdHVrZXksIGJpcmRsaWZlX2RpZmZfZGF0YSwgYygidHJvcGhpY19uaWNoZSIgPSAiY2F0ZWdvcnkiKSkKZ2dwbG90KGJpcmRsaWZlX2RpZmZfZGF0YTEsIGFlcyh4ID0gaW5jcmVhc2UsIHkgPSB0cm9waGljX25pY2hlLCBjb2xvciA9IGdyb3VwKSkgKyBnZW9tX2JveHBsb3QoKSArIHRoZW1lX2J3KCkKYGBgCgpgYGB7cn0KZ2dwbG90KGVpdGhlcl9zcGVjaWVzX2RhdGEsIGFlcyh4ID0gcmVzcG9uc2UsIHkgPSB0cm9waGljX25pY2hlLCBjb2xvciA9IHBlcmNlbnRpbGUpKSArIGdlb21fYm94cGxvdCgpICsgdGhlbWVfYncoKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoYm90aF9zcGVjaWVzX2RhdGEsIGFlcyh4ID0gcmVzcG9uc2UsIHkgPSB0cm9waGljX25pY2hlLCBjb2xvciA9IHBlcmNlbnRpbGUpKSArIGdlb21fYm94cGxvdCgpICsgdGhlbWVfYncoKQpgYGAKCmBgYHtyfQpucm93KG1lcmxpbl8xMF9kYXRhW21lcmxpbl8xMF9kYXRhJHJlc3BvbnNlID4gMCxdKQpucm93KG1lcmxpbl8yMF9kYXRhW21lcmxpbl8yMF9kYXRhJHJlc3BvbnNlID4gMCxdKQpgYGAKCmBgYHtyfQpucm93KGJpcmRsaWZlXzEwX2RhdGFbYmlyZGxpZmVfMTBfZGF0YSRyZXNwb25zZSA+IDAsXSkKbnJvdyhiaXJkbGlmZV8yMF9kYXRhW2JpcmRsaWZlXzIwX2RhdGEkcmVzcG9uc2UgPiAwLF0pCmBgYAoKYGBge3J9Cm5yb3coZWl0aGVyXzEwX2RhdGFbZWl0aGVyXzEwX2RhdGEkcmVzcG9uc2UgPiAwLF0pCm5yb3coZWl0aGVyXzIwX2RhdGFbZWl0aGVyXzIwX2RhdGEkcmVzcG9uc2UgPiAwLF0pCmBgYAoKYGBge3J9Cm5yb3coYm90aF8xMF9kYXRhW2JvdGhfMTBfZGF0YSRyZXNwb25zZSA+IDAsXSkKbnJvdyhib3RoXzIwX2RhdGFbYm90aF8yMF9kYXRhJHJlc3BvbnNlID4gMCxdKQpgYGAKCmBgYHtyfQpnZ3Bsb3QobWVybGluX3NwZWNpZXNfZGF0YSwgYWVzKHggPSByZXNwb25zZSwgeSA9IGZvcmFnaW5nX25pY2hlLCBjb2xvciA9IHBlcmNlbnRpbGUpKSArIGdlb21fYm94cGxvdCgpICsgdGhlbWVfYncoKQpgYGAKCmBgYHtyfQppbnRlcmFjdGlvbi5wbG90KG1lcmxpbl9zcGVjaWVzX2RhdGEkZm9yYWdpbmdfbmljaGUsIG1lcmxpbl9zcGVjaWVzX2RhdGEkcGVyY2VudGlsZSwgbWVybGluX3NwZWNpZXNfZGF0YSRyZXNwb25zZSkKYGBgCgpgYGB7cn0KbWVybGluX2ZvcmFnaW5nX25pY2hlX2Fub3ZhIDwtIGFvdihyZXNwb25zZX5mb3JhZ2luZ19uaWNoZSArIHBlcmNlbnRpbGUgKyBFcnJvcihuaWNoZV9uYW1lKSwgZGF0YT1tZXJsaW5fc3BlY2llc19kYXRhKQpzdW1tYXJ5KG1lcmxpbl9mb3JhZ2luZ19uaWNoZV9hbm92YSkKCm1lcmxpbl9mb3JhZ2luZ19uaWNoZV9hbm92YV9pIDwtIGFvdihyZXNwb25zZX5mb3JhZ2luZ19uaWNoZSAqIHBlcmNlbnRpbGUgKyBFcnJvcihuaWNoZV9uYW1lKSwgZGF0YT1tZXJsaW5fc3BlY2llc19kYXRhKQpzdW1tYXJ5KG1lcmxpbl9mb3JhZ2luZ19uaWNoZV9hbm92YV9pKQpgYGAKCgoKYGBge3J9CmdncGxvdChiaXJkbGlmZV9zcGVjaWVzX2RhdGEsIGFlcyh4ID0gcmVzcG9uc2UsIHkgPSBmb3JhZ2luZ19uaWNoZSwgY29sb3IgPSBwZXJjZW50aWxlKSkgKyBnZW9tX2JveHBsb3QoKSArIHRoZW1lX2J3KCkKYGBgCgpgYGB7cn0KYmlyZGxpZmVfZm9yYWdpbmdfbmljaGVfYW5vdmEgPC0gYW92KHJlc3BvbnNlfmZvcmFnaW5nX25pY2hlICsgcGVyY2VudGlsZSArIEVycm9yKG5pY2hlX25hbWUpLCBkYXRhPWJpcmRsaWZlX3NwZWNpZXNfZGF0YSkKc3VtbWFyeShiaXJkbGlmZV9mb3JhZ2luZ19uaWNoZV9hbm92YSkKCmJpcmRsaWZlX2ZvcmFnaW5nX25pY2hlX2Fub3ZhX2kgPC0gYW92KHJlc3BvbnNlfmZvcmFnaW5nX25pY2hlICogcGVyY2VudGlsZSArIEVycm9yKG5pY2hlX25hbWUpLCBkYXRhPWJpcmRsaWZlX3NwZWNpZXNfZGF0YSkKc3VtbWFyeShiaXJkbGlmZV9mb3JhZ2luZ19uaWNoZV9hbm92YV9pKQpgYGAKCgpgYGB7cn0KcGNfYXhpc19maWd1cmUgPC0gZnVuY3Rpb24oZGF0YXNldCkgewogIGFubm90YXRlX2ZpZ3VyZSgKZ2dhcnJhbmdlKAogIGdncGxvdChkYXRhc2V0LCBhZXMoeCA9IHBjMSwgeSA9IGxvZyhyZXNwb25zZSksIGNvbG9yID0gcGVyY2VudGlsZSkpICsgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKyBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKSArIHRoZW1lX2J3KCkgKyBycmVtb3ZlKCJ5bGFiIiksCiAgZ2dwbG90KGRhdGFzZXQsIGFlcyh4ID0gcGMyLCB5ID0gbG9nKHJlc3BvbnNlKSwgY29sb3IgPSBwZXJjZW50aWxlKSkgKyBnZW9tX3BvaW50KGFscGhhID0gMC41KSArIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpICsgdGhlbWVfYncoKSArIHJyZW1vdmUoInlsYWIiKSwKICBnZ3Bsb3QoZGF0YXNldCwgYWVzKHggPSBwYzMsIHkgPSBsb2cocmVzcG9uc2UpLCBjb2xvciA9IHBlcmNlbnRpbGUpKSArIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpICsgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSkgKyB0aGVtZV9idygpICsgcnJlbW92ZSgieWxhYiIpLAogIGdncGxvdChkYXRhc2V0LCBhZXMoeCA9IHBjNCwgeSA9IGxvZyhyZXNwb25zZSksIGNvbG9yID0gcGVyY2VudGlsZSkpICsgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKyBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKSArIHRoZW1lX2J3KCkgKyBycmVtb3ZlKCJ5bGFiIiksCiAgbnJvdyA9IDIsIG5jb2wgPSAyLCBjb21tb24ubGVnZW5kID0gVCwgbGFiZWwueCA9IDApLApsZWZ0ID0gdGV4dF9ncm9iKCJsb2cocmVzcG9uc2UpIiwgcm90ID0gOTApKQp9CmBgYAoKCmBgYHtyfQpwY19heGlzX2ZpZ3VyZShtZXJsaW5fc3BlY2llc19kYXRhKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGxtZTQpCm1lcmxpbl9wYzFfbW9kZWwgPSBsbWVyKHJlc3BvbnNlIH4gcGMxICogcGVyY2VudGlsZSArICgxfG5pY2hlX25hbWUpLCBkYXRhPW1lcmxpbl9zcGVjaWVzX2RhdGEpCmFub3ZhKG1lcmxpbl9wYzFfbW9kZWwpCnN1bW1hcnkobWVybGluX3BjMV9tb2RlbCkKYGBgCgpgYGB7cn0KbWVybGluX3BjMl9tb2RlbCA9IGxtZXIocmVzcG9uc2UgfiBwYzIgKiBwZXJjZW50aWxlICsgKDF8bmljaGVfbmFtZSksIGRhdGE9bWVybGluX3NwZWNpZXNfZGF0YSkKYW5vdmEobWVybGluX3BjMl9tb2RlbCkKc3VtbWFyeShtZXJsaW5fcGMyX21vZGVsKQpgYGAKCmBgYHtyfQptZXJsaW5fcGMzX21vZGVsID0gbG1lcihyZXNwb25zZSB+IHBjMyAqIHBlcmNlbnRpbGUgKyAoMXxuaWNoZV9uYW1lKSwgZGF0YT1tZXJsaW5fc3BlY2llc19kYXRhKQphbm92YShtZXJsaW5fcGMzX21vZGVsKQpzdW1tYXJ5KG1lcmxpbl9wYzNfbW9kZWwpCmBgYAoKYGBge3J9Cm1lcmxpbl9wYzRfbW9kZWwgPSBsbWVyKHJlc3BvbnNlIH4gcGM0ICogcGVyY2VudGlsZSArICgxfG5pY2hlX25hbWUpLCBkYXRhPW1lcmxpbl9zcGVjaWVzX2RhdGEpCmFub3ZhKG1lcmxpbl9wYzRfbW9kZWwpCnN1bW1hcnkobWVybGluX3BjNF9tb2RlbCkKYGBgCgpgYGB7cn0KcGNfYXhpc19maWd1cmUoYmlyZGxpZmVfc3BlY2llc19kYXRhKQpgYGAKCmBgYHtyfQpnZ3Bsb3QobWVybGluX3NwZWNpZXNfZGF0YSwgYWVzKHggPSByZXNwb25zZSwgeSA9IGlzX25vY3R1cm5hbCwgY29sb3IgPSBwZXJjZW50aWxlKSkgKyBnZW9tX2JveHBsb3QoKSArIHRoZW1lX2J3KCkKYGBgCgpgYGB7cn0KbWVybGluX25vY3R1cm5hbF9hbm92YSA8LSBhb3YocmVzcG9uc2V+aXNfbm9jdHVybmFsICsgcGVyY2VudGlsZSArIEVycm9yKG5pY2hlX25hbWUpLCBkYXRhPW1lcmxpbl9zcGVjaWVzX2RhdGEpCnN1bW1hcnkobWVybGluX25vY3R1cm5hbF9hbm92YSkKCm1lcmxpbl9ub2N0dXJuYWxfYW5vdmFfaSA8LSBhb3YocmVzcG9uc2V+aXNfbm9jdHVybmFsICogcGVyY2VudGlsZSArIEVycm9yKG5pY2hlX25hbWUpLCBkYXRhPW1lcmxpbl9zcGVjaWVzX2RhdGEpCnN1bW1hcnkobWVybGluX25vY3R1cm5hbF9hbm92YV9pKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoYmlyZGxpZmVfc3BlY2llc19kYXRhLCBhZXMoeCA9IHJlc3BvbnNlLCB5ID0gaXNfbm9jdHVybmFsLCBjb2xvciA9IHBlcmNlbnRpbGUpKSArIGdlb21fYm94cGxvdCgpICsgdGhlbWVfYncoKQpgYGAKCmBgYHtyfQpiaXJkbGlmZV9ub2N0dXJuYWxfYW5vdmEgPC0gYW92KHJlc3BvbnNlfmlzX25vY3R1cm5hbCArIHBlcmNlbnRpbGUgKyBFcnJvcihuaWNoZV9uYW1lKSwgZGF0YT1iaXJkbGlmZV9zcGVjaWVzX2RhdGEpCnN1bW1hcnkoYmlyZGxpZmVfbm9jdHVybmFsX2Fub3ZhKQoKYmlyZGxpZmVfbm9jdHVybmFsX2Fub3ZhX2kgPC0gYW92KHJlc3BvbnNlfmlzX25vY3R1cm5hbCAqIHBlcmNlbnRpbGUgKyBFcnJvcihuaWNoZV9uYW1lKSwgZGF0YT1iaXJkbGlmZV9zcGVjaWVzX2RhdGEpCnN1bW1hcnkoYmlyZGxpZmVfbm9jdHVybmFsX2Fub3ZhX2kpCmBgYAoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KSW52ZXN0aWdhdGlvbiBvZiBwZXJjZW50aWxlcyBhbmQgcHJlc2VuY2UKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmBgYHtyfQpnZ3Bsb3QobWVybGluX3NwZWNpZXNfZGF0YSwgYWVzKHggPSB0b3RhbF9zcGVjaWVzLCB5ID0gbG9nKHJlc3BvbnNlKSwgY29sb3IgPSBwZXJjZW50aWxlKSkgKyBnZW9tX3BvaW50KGFscGhhID0gMC41KSArIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpICsgdGhlbWVfYncoKQpgYGAKCmBgYHtyfQptZXJsaW5fc3BlY2llc19jb3VudF9tb2RlbCA9IGxtZXIocmVzcG9uc2UgfiB0b3RhbF9zcGVjaWVzICogcGVyY2VudGlsZSArICgxfG5pY2hlX25hbWUpLCBkYXRhPW1lcmxpbl9zcGVjaWVzX2RhdGEpCmFub3ZhKG1lcmxpbl9zcGVjaWVzX2NvdW50X21vZGVsKQpzdW1tYXJ5KG1lcmxpbl9zcGVjaWVzX2NvdW50X21vZGVsKQpgYGAKCmBgYHtyfQpiaXJkbGlmZV9zcGVjaWVzX2NvdW50X21vZGVsID0gbG1lcihyZXNwb25zZSB+IHRvdGFsX3NwZWNpZXMgKiBwZXJjZW50aWxlICsgKDF8bmljaGVfbmFtZSksIGRhdGE9YmlyZGxpZmVfc3BlY2llc19kYXRhKQphbm92YShiaXJkbGlmZV9zcGVjaWVzX2NvdW50X21vZGVsKQpzdW1tYXJ5KGJpcmRsaWZlX3NwZWNpZXNfY291bnRfbW9kZWwpCmBgYAoKYGBge3J9Cm1lcmxpbl9zcGVjaWVzX2RhdGEkcHJlc2VudCA8LSBtZXJsaW5fc3BlY2llc19kYXRhJHJlc3BvbnNlID4gMApgYGAKCmBgYHtyfQpnZ3Bsb3QobWVybGluX3NwZWNpZXNfZGF0YSwgYWVzKHggPSBsb2codG90YWxfc3BlY2llcyksIHkgPSBwcmVzZW50LCBjb2xvciA9IHBlcmNlbnRpbGUpKSArIGdlb21fYm94cGxvdCgpICsgdGhlbWVfYncoKQpgYGAKCgpgYGB7cn0KbWVybGluX3ByZXNlbnRfbW9kZWwgPSBsbWVyKHByZXNlbnQgfiBsb2codG90YWxfc3BlY2llcykgKiBwZXJjZW50aWxlICsgKDF8bmljaGVfbmFtZSksIGRhdGE9bWVybGluX3NwZWNpZXNfZGF0YSkKYW5vdmEobWVybGluX3ByZXNlbnRfbW9kZWwpCnN1bW1hcnkobWVybGluX3ByZXNlbnRfbW9kZWwpCmBgYAoKYGBge3J9CmFzc2lnbl9uaWNoZV9hcHBlYXJhbmNlX2ZhY3RvciA8LSBmdW5jdGlvbihkYXRhc2V0KSB7CiAgZGF0YXNldCRuaWNoZV9hcHBlYXJhbmNlID0gJz4gMjAlJwogIGRhdGFzZXQkbmljaGVfYXBwZWFyYW5jZVtkYXRhc2V0JHJlc3BvbnNlXzIwID4gMF0gPSAnMTAlIC0gMjAlJwogIGRhdGFzZXQkbmljaGVfYXBwZWFyYW5jZVtkYXRhc2V0JHJlc3BvbnNlXzEwID4gMF0gPSAnPCAxMCUnCiAgCiAgZGF0YXNldCRuaWNoZV9hcHBlYXJhbmNlIDwtIGZhY3RvcihkYXRhc2V0JG5pY2hlX2FwcGVhcmFuY2UsIGxldmVscyA9IGMoIjwgMTAlIiwgIjEwJSAtIDIwJSIsICI+IDIwJSIpKQogIGRhdGFzZXQKfQpgYGAKCmBgYHtyfQptZXJsaW5fZGlmZl9kYXRhIDwtIGFzc2lnbl9uaWNoZV9hcHBlYXJhbmNlX2ZhY3RvcihtZXJsaW5fZGlmZl9kYXRhKQpgYGAKCgpgYGB7cn0KZ2dwbG90KG1lcmxpbl9kaWZmX2RhdGEsIGFlcyhmaWxsPW5pY2hlX2FwcGVhcmFuY2UsIHk9dHJvcGhpY19uaWNoZSkpICsgCiAgICBnZW9tX2JhcigpCmBgYAoKYGBge3J9CmxvYWRfZXZlcl9kYXRhIDwtIGZ1bmN0aW9uKHBvb2wpIHsKICByZXNwb25zZV9uYW1lIDwtIHBhc3RlKHBvb2wsICdldmVyJywgJ3BlcmMnLCAncmF0aW8nLCBzZXAgPSAnXycpCiAgZGF0YXNldCA8LSBkYXRhX2Zvcl9yZXNwb25zZShyZXNwb25zZV9uYW1lKQogIGRhdGFzZXQkcHJlc2VudCA8LSAnWWVzJwogIGRhdGFzZXQkcHJlc2VudFtkYXRhc2V0JHJlc3BvbnNlID09IDBdIDwtICdObycKICBkYXRhc2V0JHByZXNlbnQgPC0gZmFjdG9yKGRhdGFzZXQkcHJlc2VudCwgbGV2ZWxzID0gYygiWWVzIiwgIk5vIikpCiAgZGF0YXNldAp9CmBgYAoKYGBge3J9Cm1lcmxpbl9ldmVyX2RhdGEgPC0gbG9hZF9ldmVyX2RhdGEoJ21lcmxpbicpCm1lcmxpbl9ldmVyX2RhdGEKYGBgCgpgYGB7cn0KZ2dwbG90KG1lcmxpbl9ldmVyX2RhdGEsIGFlcyhmaWxsPXByZXNlbnQsIHk9dHJvcGhpY19uaWNoZSkpICsgCiAgICBnZW9tX2JhcigpCmBgYApgYGB7cn0KYmlyZGxpZmVfZGlmZl9kYXRhIDwtIGFzc2lnbl9uaWNoZV9hcHBlYXJhbmNlX2ZhY3RvcihiaXJkbGlmZV9kaWZmX2RhdGEpCmBgYAoKCmBgYHtyfQpnZ3Bsb3QoYmlyZGxpZmVfZGlmZl9kYXRhLCBhZXMoZmlsbD1uaWNoZV9hcHBlYXJhbmNlLCB5PXRyb3BoaWNfbmljaGUpKSArIAogICAgZ2VvbV9iYXIoKQpgYGAKCgpgYGB7cn0KYmlyZGxpZmVfZXZlcl9kYXRhIDwtIGxvYWRfZXZlcl9kYXRhKCdiaXJkbGlmZScpCmBgYAoKYGBge3J9CmdncGxvdChtZXJsaW5fZXZlcl9kYXRhLCBhZXMoZmlsbD1wcmVzZW50LCB5PXRyb3BoaWNfbmljaGUpKSArIAogICAgZ2VvbV9iYXIoKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KUENBIFZhcmlhdGlvbiB3aXRoIHByZXNlbmNlCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCgpgYGB7cn0KZ2dwbG90KG1lcmxpbl9ldmVyX2RhdGEsIGFlcyhjb2xvciA9IHByZXNlbnQsIHggPSBwYzEsIHkgPSB0cm9waGljX25pY2hlKSkgKyAKICAgIGdlb21fdmlvbGluKCkgKyBnZW9tX2ppdHRlcihhZXMoZ3JvdXA9cHJlc2VudCwgc2l6ZSA9IHRvdGFsX3NwZWNpZXMpLCBwb3NpdGlvbj1wb3NpdGlvbl9qaXR0ZXJkb2RnZSgpKSArIHRoZW1lX2J3KCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iLCBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OSksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTgpLCBsZWdlbmQua2V5LnNpemUgPSB1bml0KDEsImxpbmUiKSkgKwogICAgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZCh0aXRsZT0iUHJlc2VudCBpbiBhbnkgY2l0eT8iKSwgc2l6ZT1ndWlkZV9sZWdlbmQodGl0bGU9Ik5pY2hlIHNpemUiKSkgKwogICAgeWxhYigiVHJvcGhpYyBOaWNoZSIpICsgeGxhYigiUEMxOiBCb2R5IHNpemUiKSArIGxhYnModGl0bGUgPSAiTWVybGluIFJlZ2lvbmFsIFBvb2wiKQpnZ3NhdmUoInNwZWNpZXNfYW5hbHlzaXNfcGMxX21lcmxpbi5qcGciKQpgYGAKYGBge3J9CmdncGxvdChtZXJsaW5fZGlmZl9kYXRhLCBhZXMoY29sb3IgPSBuaWNoZV9hcHBlYXJhbmNlLCB4ID0gcGMxLCB5ID0gdHJvcGhpY19uaWNoZSkpICsgCiAgICBnZW9tX3Zpb2xpbigpCmBgYAoKCmBgYHtyfQpnZ3Bsb3QobWVybGluX2V2ZXJfZGF0YSwgYWVzKGNvbG9yID0gcHJlc2VudCwgeCA9IHBjMiwgeSA9IHRyb3BoaWNfbmljaGUpKSArIAogICAgZ2VvbV92aW9saW4oKQpgYGAKYGBge3J9CmdncGxvdChtZXJsaW5fZXZlcl9kYXRhLCBhZXMoY29sb3IgPSBwcmVzZW50LCB4ID0gcGMzLCB5ID0gdHJvcGhpY19uaWNoZSkpICsgCiAgICBnZW9tX3Zpb2xpbigpCmBgYApgYGB7cn0KZ2dwbG90KG1lcmxpbl9ldmVyX2RhdGEsIGFlcyhjb2xvciA9IHByZXNlbnQsIHggPSBwYzQsIHkgPSB0cm9waGljX25pY2hlKSkgKyAKICAgIGdlb21fdmlvbGluKCkKYGBgCgoKYGBge3J9CmdncGxvdChiaXJkbGlmZV9ldmVyX2RhdGEsIGFlcyhjb2xvciA9IHByZXNlbnQsIHggPSBwYzEsIHkgPSB0cm9waGljX25pY2hlKSkgKyAKICAgIGdlb21fdmlvbGluKCkgKyBnZW9tX2ppdHRlcihhZXMoZ3JvdXA9cHJlc2VudCwgc2l6ZSA9IHRvdGFsX3NwZWNpZXMpLCBwb3NpdGlvbj1wb3NpdGlvbl9qaXR0ZXJkb2RnZSgpKSArIHRoZW1lX2J3KCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iLCBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OSksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTgpLCBsZWdlbmQua2V5LnNpemUgPSB1bml0KDEsImxpbmUiKSkgKwogICAgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZCh0aXRsZT0iUHJlc2VudCBpbiBhbnkgY2l0eT8iKSwgc2l6ZT1ndWlkZV9sZWdlbmQodGl0bGU9Ik5pY2hlIHNpemUiKSkgKwogICAgeWxhYigiVHJvcGhpYyBOaWNoZSIpICsgeGxhYigiUEMxOiBCb2R5IHNpemUiKSArIGxhYnModGl0bGUgPSAiQmlyZGxpZmUgUmVnaW9uYWwgUG9vbCIpCmdnc2F2ZSgic3BlY2llc19hbmFseXNpc19wYzFfYmlyZGxpZmUuanBnIikKYGBgCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KRmlyc3QgYXR0ZW1wdCBmaWd1cmVzCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmBgYHtyfQp0aGVtZSA8LSAgdGhlbWVfYncoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIiwgbGVnZW5kLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTkpLCBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT04KSwgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjUsImxpbmUiKSkKZ3VpZGVfZXZlciA8LSBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQodGl0bGU9IlByZXNlbnQgaW4gYW55IGNpdHk/IikpCmd1aWRlX3BlcmNlbnRpbGUgPC0gZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJUb3AgWCUgb2YgcmFua2VkIHNwZWNpZXMiLCBucm93ID0gMykpCgpzcGVjaWVzX3Bsb3QxIDwtIGFubm90YXRlX2ZpZ3VyZSgKICBnZ2FycmFuZ2UoCiAgICBnZ3Bsb3QobWVybGluX2V2ZXJfZGF0YSwgYWVzKGZpbGw9cHJlc2VudCwgeT10cm9waGljX25pY2hlKSkgKyBnZW9tX2JhcigpICsgdGhlbWUgKyBndWlkZV9ldmVyICsgcnJlbW92ZSgieGxhYiIpICsgcnJlbW92ZSgieWxhYiIpICsgbGFicyh0aXRsZSA9ICJNZXJsaW4iKSwKICAgIGdncGxvdChiaXJkbGlmZV9ldmVyX2RhdGEsIGFlcyhmaWxsPXByZXNlbnQsIHk9dHJvcGhpY19uaWNoZSkpICsgZ2VvbV9iYXIoKSArIHRoZW1lICsgZ3VpZGVfZXZlciArIHJyZW1vdmUoInhsYWIiKSArIHJyZW1vdmUoInlsYWIiKSArIGxhYnModGl0bGUgPSAiQmlyZGxpZmUiKSwKICAgIGdncGxvdChtZXJsaW5fZGlmZl9kYXRhLCBhZXMoZmlsbD1uaWNoZV9hcHBlYXJhbmNlLCB5PXRyb3BoaWNfbmljaGUpKSArICBnZW9tX2JhcigpKyB0aGVtZSArIGd1aWRlX3BlcmNlbnRpbGUgKyBycmVtb3ZlKCJ4bGFiIikgKyBycmVtb3ZlKCJ5bGFiIiksCiAgICBnZ3Bsb3QoYmlyZGxpZmVfZGlmZl9kYXRhLCBhZXMoZmlsbD1uaWNoZV9hcHBlYXJhbmNlLCB5PXRyb3BoaWNfbmljaGUpKSArIGdlb21fYmFyKCkgKyB0aGVtZSArIGd1aWRlX3BlcmNlbnRpbGUgKyBycmVtb3ZlKCJ4bGFiIikgKyBycmVtb3ZlKCJ5bGFiIiksCiAgICBucm93ID0gMiwgbmNvbCA9IDIsIGNvbW1vbi5sZWdlbmQgPSBGLCBsYWJlbC54ID0gMCwgbGFiZWxzID0gYygiYSkiLCAiIiwgImIpIiwgIiIpKSwKbGVmdCA9IHRleHRfZ3JvYigiVHJvcGhpYyBOaWNoZSIsIHJvdCA9IDkwKSwKYm90dG9tID0gdGV4dF9ncm9iKCJOaWNoZSBDb3VudCIpKQoKc3BlY2llc19wbG90MQpgYGAKYSkgTmljaGVzIHJlY29yZGVkIHByZXNlbnQgaW4gYXQgbGVhc3Qgb25lIGNpdHkuCmIpIEdpdmVuIHNwZWNpZXMgcmFua2VkIGJ5IHBlcmNlbnRhZ2Ugb2YgY2l0aWVzIHBvcHVsYXRlZCBnaXZlbiB0aGV5IGFyZSBwcmVzZW50IGluIHJlZ2lvbmFsIHBvb2w7IFRoaXMgc2hvd3MgbmljaGVzIHByZXNlbnQgd2l0aCB0aGUgdG9wIDEwJSBvZiB0aGUgbW9zdCB1cmJhbmlzZWQgc3BlY2llcyAocmVkKSwgdGhlIHRvcCAyMCUgb2YgdGhlIG1vc3QgdXJiYW5pc2VkIHNwZWNpZXMgKHJlZCArIGdyZWVuKSwgYW5kIHRoZW4gdGhlIHJlbWFpbmluZyBuaWNoZXMgKGJsdWUpLiBUaGlzIGFwcHJveGltYXRlcyB0byB0aGUgbmljaGVzIHRoYXQgd291bGQgYmUgcHJlc2VudCBpbiB0aGUgYm90dG9tIDI1JSBwZXJmb3JtaW5nIGhvdHNwb3RzIChyZWQpLCB0aGUgYm90dG9tIDc1JSBwZXJmb3JtaW5nIGhvdHNwb3RzIChyZWQgKyBncmVlbiksIGFuZCB0aGVuIHRoZSBuaWNoZXMgYXQgdGhlIGhpZ2hlc3QgcGVyZm9ybWluZyBob3RzcG90cyBvciBuaWNoZXMgdGhhdCBhcmUgbmV2ZXIgcHJlc2VudCAoYmx1ZSkuCgpgYGB7cn0KZ3VpZGVfcGVyY2VudGlsZV8yIDwtIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQodGl0bGU9IlBlcmNlbnRpbGUiKSkKZ3VpZGVfaW5jcmVhc2UgPC0gZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZCh0aXRsZT0iVHVrZXkgcmVzcG9uc2UgZ3JvdXAiLCBucm93ID0gMikpCgpzcGVjaWVzX3Bsb3QyIDwtIGFubm90YXRlX2ZpZ3VyZSgKICBnZ2FycmFuZ2UoCiAgICBnZ3Bsb3QobWVybGluX3NwZWNpZXNfZGF0YSwgYWVzKHggPSByZXNwb25zZSwgeSA9IHRyb3BoaWNfbmljaGUsIGNvbG9yID0gcGVyY2VudGlsZSkpICsgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZSAgKyBndWlkZV9wZXJjZW50aWxlXzIgKyB4bGFiKCJGdWxsbmVzcyIpICsgcnJlbW92ZSgieWxhYiIpICsgbGFicyh0aXRsZSA9ICJNZXJsaW4iKSwKICAgIGdncGxvdChiaXJkbGlmZV9zcGVjaWVzX2RhdGEsIGFlcyh4ID0gcmVzcG9uc2UsIHkgPSB0cm9waGljX25pY2hlLCBjb2xvciA9IHBlcmNlbnRpbGUpKSArIGdlb21fYm94cGxvdCgpICsgdGhlbWUgKyBndWlkZV9wZXJjZW50aWxlXzIgKyB4bGFiKCJGdWxsbmVzcyIpICsgcnJlbW92ZSgieWxhYiIpICsgbGFicyh0aXRsZSA9ICJCaXJkbGlmZSIpLAogICAgZ2dwbG90KG1lcmxpbl9kaWZmX2RhdGExLCBhZXMoeCA9IGluY3JlYXNlLCB5ID0gdHJvcGhpY19uaWNoZSwgY29sb3IgPSBncm91cCkpICsgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZSArIGd1aWRlX2luY3JlYXNlICsgeGxhYigiSW5jcmVhc2UgaW4gZnVsbG5lc3MiKSArIHJyZW1vdmUoInlsYWIiKSwKICAgIGdncGxvdChiaXJkbGlmZV9kaWZmX2RhdGExLCBhZXMoeCA9IGluY3JlYXNlLCB5ID0gdHJvcGhpY19uaWNoZSwgY29sb3IgPSBncm91cCkpICsgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZSArIGd1aWRlX2luY3JlYXNlICsgeGxhYigiSW5jcmVhc2UgaW4gZnVsbG5lc3MiKSArIHJyZW1vdmUoInlsYWIiKSwgCiAgICBucm93ID0gMiwgbmNvbCA9IDIsIGNvbW1vbi5sZWdlbmQgPSBGLCBsYWJlbC54ID0gMCwgbGFiZWxzID0gYygiYykiLCAiIiwgImQpIiwgIiIpKSwKbGVmdCA9IHRleHRfZ3JvYigiVHJvcGhpYyBOaWNoZSIsIHJvdCA9IDkwKSkKCnNwZWNpZXNfcGxvdDIKYGBgCmMpIFRoZSByZWR1bmRhbmN5L2Z1bGxuZXNzIG9mIHRoZSBuaWNoZXMgdGhhdCBhcmUgcHJlc2VudCBpbiBjaXRpZXMgd2l0aCAxMCUgb2YgdGhlIG1vc3QgdXJiYW5pc2VkIHNwZWNpZXMsIGFuZCB0aGUgcmVkdW5kYW5jeS9mdWxsbmVzcyBvZiB0aGUgbmljaGVzIHRoYXQgYXJlIHByZXNlbnQgaW4gY2l0aWVzIHdpdGggMjAlIG9mIHRoZSBtb3N0IHVyYmFuaXNlZCBzcGVjaWVzLgpkKSBUaGUgcGVyY2VudGFnZSBpbmNyZWFzZSBpbiByZWR1bmRhbmN5L2Z1bGxuZXNzIG9mIG5pY2hlcyBiZXR3ZWVuIHRoZSB0b3AgMTAlIG9mIG1vc3QgdXJiYW5pc2VkIHNwZWNpZXMgYW5kIHRoZSB0b3AgMjAlIG9mIG1vc3QgdXJiYW5pc2VkIHNwZWNpZXMsIGdyb3VwZWQgdXNpbmcgVHVrZXkgYmFzZWQgb24gYW4gYW5vdmEgb2YgdGhlIHBlcmNlbnRhZ2UgaW5jcmVhc2UgZ2l2ZW4gdGhlIHRyb3BpYyBuaWNoZS4gVGhpcyBzaG93cyB0aGUgYW1vdW50IG9mIHJlZHVuZGFuY3kgdGhhdCBpcyBpbmNyZWFzZWQgZnJvbSB0aGUgYm90dG9tIDI1JSBwZXJmb3JtaW5nIGhvdHNwb3RzIChob3RzcG90cyB3aXRoIDEwJSBvZiByZWdpb25hbCBwb29sKSBhbmQgdGhlIGJvdHRvbSA3NSUgb2YgcGVyZm9ybWluZyBob3RzcG90cyAoaG90c3BvdHMgd2l0aCAyMCUgb2YgcmVnaW9uYWwgcG9vbCkuCgoKYGBge3J9CmpwZWcoInNwZWNpZXNfcGxvdDEuanBnIiwgd2lkdGggPSA4MDAsIGhlaWdodCA9IDYwMCkKc3BlY2llc19wbG90MQpkZXYub2ZmKCkKCmpwZWcoInNwZWNpZXNfcGxvdDIuanBnIiwgd2lkdGggPSA4MDAsIGhlaWdodCA9IDYwMCkKc3BlY2llc19wbG90MgpkZXYub2ZmKCkKYGBgCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tClRyb3BoaWMgTmljaGUgQWNjdW11bGF0aW9uCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmBgYHtyfQphY2N1bXVsYXRpb24gPC0gcmVhZF9jc3YoJ3Ryb3BoaWNfbmljaGVfYWNjdW11bGF0aW9uLmNzdicpCmFjY3VtdWxhdGlvbgpgYGAKYGBge3J9Cm1lcmxpbl9hY2N1bXVsYXRpb24gPSBnZ3Bsb3QoYWNjdW11bGF0aW9uLCBhZXMoeCA9IHBlcmNlbnQsIHkgPSBtZXJsaW5fbmljaGVfY291bnQpKSArIAogIGdlb21fbGluZShsaW5ldHlwZSA9ICJkb3R0ZWQiKSArIAogIGdlb21fbGluZShhZXMobGluZXR5cGUgPSBtZXJsaW5fcmVtYWluaW5nX3NwZWNpZXMpLCBuYS52YWx1ZSA9ICJkYXNoIikgKwogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCh2YWx1ZXM9YygiYmxhbmsiLCAic29saWQiKSwgZ3VpZGUgPSAibm9uZSIpICsKICBnZW9tX2hsaW5lKGRhdGEgPSAuICU+JSBncm91cF9ieSh0cm9waGljX25pY2hlKSAlPiUgZmlsdGVyKG1lcmxpbl9uaWNoZV9jb3VudCA9PSBtYXgobWVybGluX25pY2hlX2NvdW50KSksIGFlcyh5aW50ZXJjZXB0ID0gbWVybGluX25pY2hlX2NvdW50KSwgY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAwLjI1LCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDYpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBzaXplID0gNiksICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gNikpICsKICBmYWNldF93cmFwICh+IHRyb3BoaWNfbmljaGUpICsKICB4bGFiKCJQZXJjZW50YWdlIG9mIGFsbCBTcGVjaWVzIikgKyAKICB5bGFiKCJOdW1iZXIgb2YgTmljaGVzIikgKwogIGxhYnModGl0bGUgPSAiTWVybGluIE5pY2hlIEFjY3VtdWxhdGlvbiIpCgptZXJsaW5fYWNjdW11bGF0aW9uCmBgYAoKCmBgYHtyfQpiaXJkbGlmZV9hY2N1bXVsYXRpb24gPSBnZ3Bsb3QoYWNjdW11bGF0aW9uLCBhZXMoeCA9IHBlcmNlbnQsIHkgPSBiaXJkbGlmZV9uaWNoZV9jb3VudCkpICsgCiAgZ2VvbV9saW5lKGxpbmV0eXBlID0gImRvdHRlZCIpICsgCiAgZ2VvbV9saW5lKGFlcyhsaW5ldHlwZSA9IGJpcmRsaWZlX3JlbWFpbmluZ19zcGVjaWVzKSwgbmEudmFsdWUgPSAiZGFzaCIpICsKICBzY2FsZV9saW5ldHlwZV9tYW51YWwodmFsdWVzPWMoImJsYW5rIiwgInNvbGlkIiksIGd1aWRlID0gIm5vbmUiKSArCiAgZ2VvbV9obGluZShkYXRhID0gLiAlPiUgZ3JvdXBfYnkodHJvcGhpY19uaWNoZSkgJT4lIGZpbHRlcihiaXJkbGlmZV9uaWNoZV9jb3VudCA9PSBtYXgoYmlyZGxpZmVfbmljaGVfY291bnQpKSwgYWVzKHlpbnRlcmNlcHQgPSBiaXJkbGlmZV9uaWNoZV9jb3VudCksIGNvbG9yID0gImJsdWUiLCBzaXplID0gMC4yNSwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA2KSwgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgc2l6ZSA9IDYpLCAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDYpKSArCiAgZmFjZXRfd3JhcCAofiB0cm9waGljX25pY2hlKSArCiAgeGxhYigiUGVyY2VudGFnZSBvZiBhbGwgU3BlY2llcyIpICsgCiAgeWxhYigiTnVtYmVyIG9mIE5pY2hlcyIpICsKICBsYWJzKHRpdGxlID0gIkJpcmRsaWZlIE5pY2hlIEFjY3VtdWxhdGlvbiIpCgpiaXJkbGlmZV9hY2N1bXVsYXRpb24KYGBgCmBgYHtyfQphbm5vdGF0ZV9maWd1cmUoCiAgZ2dhcnJhbmdlKG1lcmxpbl9hY2N1bXVsYXRpb24gKyBycmVtb3ZlKCJ4bGFiIikgKyBycmVtb3ZlKCJ5bGFiIiksIAogICAgICAgICAgICBiaXJkbGlmZV9hY2N1bXVsYXRpb24gKyBycmVtb3ZlKCJ4bGFiIikgKyBycmVtb3ZlKCJ5bGFiIiksCiAgICAgICAgICAgIG5jb2wgPSAyLCBsYWJlbC54ID0gMCksCmxlZnQgPSB0ZXh0X2dyb2IoIk51bWJlciBvZiBOaWNoZXMgUHJlc2VudCIsIHJvdCA9IDkwKSwKYm90dG9tID0gdGV4dF9ncm9iKCJQZXJjZW50YWdlIG9mIGFsbCBTcGVjaWVzIC0gcmFua2VkIGJ5IHVyYmFuaXNhdGlvbiIpKQoKCmdnc2F2ZSgidHJvcGhpY19uaWNoZV9hY2N1bWxhdGlvbi5qcGciKQpgYGAKYGBge3J9CmJ5X21heF9iaXJkbGlmZV9uaWNoZV9jb3VudCA9IGFjY3VtdWxhdGlvbiAlPiUgZ3JvdXBfYnkodHJvcGhpY19uaWNoZSkgJT4lIHN1bW1hcmlzZShWYWx1ZSA9IG1heChiaXJkbGlmZV9uaWNoZV9jb3VudCkpCmJ5X21heF9iaXJkbGlmZV9uaWNoZV9jb3VudFtvcmRlcigtYnlfbWF4X2JpcmRsaWZlX25pY2hlX2NvdW50JFZhbHVlKSxdCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMn0KZ2dwbG90KGFjY3VtdWxhdGlvbiwgYWVzKHggPSBwZXJjZW50LCB5ID0gYmlyZGxpZmVfbmljaGVfY291bnQpKSArIAogIGdlb21fbGluZShsaW5ldHlwZSA9ICJkb3R0ZWQiKSArIAogIGdlb21fbGluZShhZXMobGluZXR5cGUgPSBiaXJkbGlmZV9yZW1haW5pbmdfc3BlY2llcyksIG5hLnZhbHVlID0gImRhc2giKSArCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKHZhbHVlcz1jKCJibGFuayIsICJzb2xpZCIpLCBndWlkZSA9ICJub25lIikgKwogIGdlb21faGxpbmUoZGF0YSA9IC4gJT4lIGdyb3VwX2J5KHRyb3BoaWNfbmljaGUpICU+JSBmaWx0ZXIoYmlyZGxpZmVfbmljaGVfY291bnQgPT0gbWF4KGJpcmRsaWZlX25pY2hlX2NvdW50KSksIGFlcyh5aW50ZXJjZXB0ID0gYmlyZGxpZmVfbmljaGVfY291bnQpLCBjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDAuMjUsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNiksIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHNpemUgPSA2KSwgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA2KSkgKwogIGZhY2V0X3dyYXAgKH4gZmFjdG9yKHRyb3BoaWNfbmljaGUsIGxldmVscyA9IGMoIkludmVydGl2b3JlIiwgIkFxdWF0aWMgcHJlZGF0b3IiLCAiT21uaXZvcmUiLCAiVmVydGl2b3JlIiwgIkZydWdpdm9yZSIsICJIZXJiaXZvcmUgYXF1YXRpYyIsICJHcmFuaXZvcmUiLCAiSGVyYml2b3JlIHRlcnJlc3RyaWFsIiwgIk5lY3Rhcml2b3JlIiwgIlNjYXZlbmdlciIpKSwgc2NhbGVzID0gImZyZWUiKSArCiAgeGxhYigiUGVyY2VudGFnZSBvZiBhbGwgU3BlY2llcyIpICsgCiAgeWxhYigiTnVtYmVyIG9mIE5pY2hlcyIpICsKICBsYWJzKHRpdGxlID0gIkJpcmRsaWZlIE5pY2hlIEFjY3VtdWxhdGlvbiIpICsKICB4bGltKDAsIDUwKQpgYGAKCgoKCgoKCgoK